Foren

Attached files in an email client portlet, how to

thumbnail
Jose Alvarez de Lara, geändert vor 11 Jahren.

Attached files in an email client portlet, how to

Junior Member Beiträge: 45 Beitrittsdatum: 10.12.12 Neueste Beiträge
Hi,

I am trying an email client portlet but need to resolve how to attach several files to my email.
I was wondering in something like,


<h:form id="f3" enctype="multipart/form-data">
        <h:messages />
        <h:panelgrid columns="1">
                <bridge:inputfile fileUploadListener="#{applicantBackingBean.handleFileUpload}" multiple />
        </h:panelgrid>
        <h:commandbutton value="#{i18n['submit']}" />
</h:form>


being this case the JSF2 implementation of the JSF2 Portlet example (JSF2 Portlet). I am not sure if it is correct but what I pretend is for every file I attach the jsp reload waiting for a new attachment or send the email.

Best regards,
jose
thumbnail
Jose Alvarez de Lara, geändert vor 11 Jahren.

RE: Attached files in an email client portlet, how to

Junior Member Beiträge: 45 Beitrittsdatum: 10.12.12 Neueste Beiträge
At the end I would like to have something like this,


<h:form id="f2" enctype="multipart/form-data">
	<h:messages globalOnly="true" layout="table" />
	<h3>#{i18n['attachments']}</h3>
	<h:datatable headerclass="portlet-section-header results-header" rowclasses="portlet-section-body results-row, portlet-section-alternate results-row alt" value="#{applicantModelBean.uploadedFiles}" var="uploadedFile">
		<h:column>
			<f:facet name="header">
				<h:outputtext value="#{i18n['file-name']}" />
			</f:facet>
			<h:outputtext value="#{uploadedFile.name}" />
		</h:column>
		<h:column>
			<f:facet name="header">
				<h:outputtext value="#{i18n['size']}" />
			</f:facet>
			<h:outputtext value="#{uploadedFile.size}" />
		</h:column>
	</h:datatable>
	<h:panelgrid columns="1">
		<bridge:inputfile fileUploadListener="#{applicantBackingBean.handleFileUpload}" multiple />
	</h:panelgrid>
	<h:commandbutton value="#{i18n['submit']}" />
</h:form>
thumbnail
Jose Alvarez de Lara, geändert vor 11 Jahren.

RE: Attached files in an email client portlet, how to

Junior Member Beiträge: 45 Beitrittsdatum: 10.12.12 Neueste Beiträge
This is what I did.

Following the 2012 JSF2 Portlet architecture I have built another webapp that simplify that portlet and add a
new ManagedBean EmailSenderServiceBean in the package com.liferay.faces.demos.bean. Here is my bean,


@ManagedBean(name = "emailSenderServiceBean")
@ViewScoped
public class EmailSenderServiceBean implements Serializable {

	private static final long serialVersionUID = -6903026987077945240L;
	
	private static final Properties properties = new Properties();
	private static final String username = "myuser@gmail.com";
	private static final String password = "mypass";
	
	private Session session;
	private List<uploadedfile> files;
	private String to;
	private String subject;
	private String messageBodyText;
	
	private void init() {

		properties.put("mail.smtp.host", "smtp.gmail.com");
		properties.put("mail.smtp.starttls.enable", "true");
		properties.put("mail.smtp.port", 587);
		properties.put("mail.smtp.mail.sender","myuser@gmail.com");
		properties.put("mail.smtp.user", username);
		properties.put("mail.smtp.auth", "true");

		session = Session.getDefaultInstance(properties);
	}

	public void sendEmail(){

		init();
		try{
			
			MimeMessage message = new MimeMessage(session);
			message.setFrom(new InternetAddress((String)properties.get("mail.smtp.mail.sender")));
			message.addRecipient(Message.RecipientType.TO, new InternetAddress(getTo()));
			message.setSubject(getSubject());
			message.setText(getMessageBodyText());
			
			if(files.size() &gt; 0) {
				Multipart multipart = new MimeMultipart();
				for(UploadedFile uf: files) {
					addAttachment(multipart, uf);
				}
				message.setContent(multipart);
			}
			
			Transport t = session.getTransport("smtp");
			t.connect((String)properties.get("mail.smtp.user"), password);
			t.sendMessage(message, message.getAllRecipients());
			t.close();
		}catch (MessagingException me){
            me.printStackTrace();
			return;
		}
		
	}
	
	private static void addAttachment(Multipart multipart, UploadedFile uFile)
			throws MessagingException {
	    DataSource source = new FileDataSource(uFile.getAbsolutePath());
	    BodyPart messageBodyPart = new MimeBodyPart();
	    messageBodyPart.setDataHandler(new DataHandler(source));
	    messageBodyPart.setFileName(uFile.getName());
	    multipart.addBodyPart(messageBodyPart);
	}
	
	public void reset() {
		to = null;
		subject = null;
		messageBodyText = null;
		files.clear();
	}
	
	/*
	public static void main(String args[]) {
		EmailSenderService ess = new EmailSenderService();
		ess.sendEmail();
	}
	*/

	public List<uploadedfile> getFiles() {
		return files;
	}

	public void setFiles(List<uploadedfile> files) {
		this.files = files;
	}

	public String getTo() {
		return to;
	}

	public void setTo(String to) {
		this.to = to;
	}

	public String getSubject() {
		return subject;
	}

	public void setSubject(String subject) {
		this.subject = subject;
	}

	public String getMessageBodyText() {
		return messageBodyText;
	}

	public void setMessageBodyText(String messageBodyText) {
		this.messageBodyText = messageBodyText;
	}
}
</uploadedfile></uploadedfile></uploadedfile>


At the end I have substituted the firstNameField etc for the fields emailTo, subject and messageText and
on the other hand I use a similar code to get the differents files to attach to the email from the layer view.

Here is the code for the submit method in the ApplicantBackingBean.java file,


	public String submit() {

		if (logger.isDebugEnabled()) {
			logger.debug("emailTo=" + applicantModelBean.getEmailTo());
			logger.debug("subject=" + applicantModelBean.getSubject());
			logger.debug("messageText=" + applicantModelBean.getMessageText());
			
			List<uploadedfile> uploadedFiles = applicantModelBean.getUploadedFiles();

			for (UploadedFile uploadedFile : uploadedFiles) {
				logger.debug("uploadedFile=[{0}]", uploadedFile.getName());
			}
		}

		// Delete the uploaded files.
		try {
			
			List<uploadedfile> uploadedFiles = applicantModelBean.getUploadedFiles();
			
                        /*
			emailSenderServiceBean.setTo(applicantModelBean.getEmailTo());
			emailSenderServiceBean.setSubject(applicantModelBean.getSubject());
			emailSenderServiceBean.setMessageBodyText(applicantModelBean.getMessageText());
			emailSenderServiceBean.setFiles(uploadedFiles);
			emailSenderServiceBean.sendEmail();
			emailSenderServiceBean.reset();
			*/
			
                        for (UploadedFile uploadedFile : uploadedFiles) {
				uploadedFile.delete();
				logger.debug("Deleted file=[{0}]", uploadedFile.getName());
			}

			// Store the applicant's first name in JSF 2 Flash Scope so that it can be picked up
			// for use inside of confirmation.xhtml
			FacesContext facesContext = FacesContext.getCurrentInstance();
			facesContext.getExternalContext().getFlash().put("subject", applicantModelBean.getSubject());

			applicantModelBean.clearProperties();

			return "success";

		}
		catch (Exception e) {
			logger.error(e.getMessage(), e);
			FacesMessageUtil.addGlobalUnexpectedErrorMessage(FacesContext.getCurrentInstance());

			return "failure";
		}
	}
</uploadedfile></uploadedfile>


where emailSenderServiceBean is declared in the backing bean as a managed property

@ManagedProperty(value = "#{emailSenderServiceBean}")
private transient EmailSenderServiceBean emailSenderServiceBean;

But still does not work. I am thinking of the configurartion files in the WEB-INF folder. Just debugging these files I am getting
at less to deploy the portlet though it gives an error and doses not display the controlls.

Any help or suggestion should be appreciated.

Kind regards,
Jose
thumbnail
Jose Alvarez de Lara, geändert vor 11 Jahren.

RE: Attached files in an email client portlet, how to

Junior Member Beiträge: 45 Beitrittsdatum: 10.12.12 Neueste Beiträge
Hi,

I have could get it works. Here is my applicant.xhtml file


<!--?xml version="1.0"?-->
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:aui="http://liferay.com/faces/aui" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:bridge="http://liferay.com/faces/bridge" xmlns:example-cc="http://java.sun.com/jsf/composite/example-cc" xmlns:ui="http://java.sun.com/jsf/facelets">

	<aui:layout id="l1">
		<example-cc:clipboard label="#{i18n['email-client']}" />
		<example-cc:sponsorbutton />
		<example-cc:divider />
		<aui:column id="c1">
			<h:form id="f1">
				<h:messages globalOnly="true" layout="table" />
				<aui:fieldset id="fs1">
					<aui:column id="c1a">
						<aui:field id="emailToField" label="#{i18n['email-to']}">
							<h:inputtext id="emailTo" required="true" validatormessage="#{i18n['invalid-email-address']}" value="#{applicantModelBean.emailTo}">
								<f:validateregex pattern=".+[@].+[.].+" />
								<f:ajax render="emailToField" />
							</h:inputtext>
							<h:message for="emailTo" />
						</aui:field>
						<aui:field id="subjectField" label="#{i18n['subject']}">
							<h:inputtext id="subject" required="true" value="#{applicantModelBean.subject}">
								<f:ajax render="subjectField" />
							</h:inputtext>
							<h:message for="subject" />
						</aui:field>
						<aui:field id="messageBodyTextField" label="#{i18n['message-body-text']}">
							<h:inputtextarea id="messageText" required="true" cols="75" rows="35" value="#{applicantModelBean.messageText}">
								<f:ajax render="messageBodyTextField" />
							</h:inputtextarea>
							<h:message for="messageText" />
						</aui:field>
					</aui:column>
				</aui:fieldset>
				<hr>
				<h:commandbutton action="#{applicantBackingBean.submit}" value="#{i18n['submit']}">
					<f:ajax execute="@form" render="@form" />
				</h:commandbutton>
				<!-- Test 5.4.2 Encoding PortletMode changes in Faces navigation -->
				<h:commandbutton action="/views/portletEditMode.xhtml?javax.portlet.faces.PortletMode=edit&amp;javax.portlet.faces.WindowState=maximized" immediate="true" value="#{i18n['edit-preferences']}" />
			</h:form>
		</aui:column>
		<aui:column id="c2">
			<aui:column id="c2a" styleclass="uploaded-files">
				<h:form id="f2">
					<h3>#{i18n['attachments']}</h3>
					<h:datatable headerclass="portlet-section-header results-header" rowclasses="portlet-section-body results-row, portlet-section-alternate results-row alt" value="#{applicantModelBean.uploadedFiles}" var="uploadedFile">
						<h:column>
							<h:commandbutton actionlistener="#{applicantBackingBean.deleteUploadedFile}" image="#{resource['example:icon-delete.png']}" onclick="if (! confirm('#{i18n['are-you-sure-you-want-to-delete-this']}')) {return false;}" value="#{uploadedFile.id}">
								<f:ajax render="@form" />
							</h:commandbutton>
						</h:column>
						<h:column>
							<f:facet name="header">
								<h:outputtext value="#{i18n['file-name']}" />
							</f:facet>
							<h:outputtext value="#{uploadedFile.name}" />
						</h:column>
						<h:column>
							<f:facet name="header">
								<h:outputtext value="#{i18n['size']}" />
							</f:facet>
							<h:outputtext value="#{uploadedFile.size}" />
						</h:column>
					</h:datatable>
				</h:form>
				<hr>
				<h:form id="f3" enctype="multipart/form-data">
					<h:panelgrid columns="1">
						<bridge:inputfile fileUploadListener="#{applicantBackingBean.handleFileUpload}" multiple />
					</h:panelgrid>
					<h:commandbutton value="#{i18n['submit']}" />
				</h:form>
			</aui:column>
		</aui:column>
	</aui:layout>

</ui:composition>


and here are the backing beans,

ApplicantBackingBean.-

@ManagedBean(name = "applicantBackingBean")
@ViewScoped
public class ApplicantBackingBean implements Serializable {

	// serialVersionUID
	private static final long serialVersionUID = 2947548873495692163L;

	// Logger
	private static final transient Logger logger = LoggerFactory.getLogger(ApplicantBackingBean.class);

	// Injections
	@ManagedProperty(value = "#{applicantModelBean}")
	private transient ApplicantModelBean applicantModelBean;
	@ManagedProperty(value = "#{emailSenderServiceBean}")
	private transient EmailSenderServiceBean emailSenderServiceBean;
	
	public void deleteUploadedFile(ActionEvent actionEvent) {
	    UICommand uiCommand = (UICommand)actionEvent.getComponent();
	    String fileId = (String)uiCommand.getValue();
	    try
	    {
	      List<uploadedfile> uploadedFiles = this.applicantModelBean.getUploadedFiles();
	
	      UploadedFile uploadedFileToDelete = null;
	
	      for (UploadedFile uploadedFile : uploadedFiles)
	      {
	        if (uploadedFile.getId().equals(fileId)) {
	          uploadedFileToDelete = uploadedFile;
	
	          break;
	        }
	      }
	
	      if (uploadedFileToDelete != null) {
	        uploadedFileToDelete.delete();
	        uploadedFiles.remove(uploadedFileToDelete);
	        logger.debug("Deleted file=[{0}]", new Object[] { uploadedFileToDelete.getName() });
	      }
	    }
	    catch (Exception e) {
	      logger.error(e);
	    }
	  }
	
	public void handleFileUpload(FileUploadEvent fileUploadEvent) throws Exception {
	    List<uploadedfile> uploadedFiles = this.applicantModelBean.getUploadedFiles();
	    UploadedFile uploadedFile = fileUploadEvent.getUploadedFile();
	
	    if (uploadedFile != null)
	    {
	      if (uploadedFile.getStatus() == UploadedFile.Status.FILE_SAVED) {
	        uploadedFiles.add(uploadedFile);
	        logger.debug("Received fileName=[{0}] absolutePath=[{1}]", new Object[] { uploadedFile.getName(), uploadedFile.getAbsolutePath() });
	      }
	      else
	      {
	        logger.error("Uploaded file status=[" + uploadedFile.getStatus().toString() + "] " + uploadedFile.getMessage());
	
	        FacesMessageUtil.addGlobalUnexpectedErrorMessage(FacesContext.getCurrentInstance());
	      }
	    }
	  }

	public String submit() {

		if (logger.isDebugEnabled()) {
			logger.debug("emailTo=" + applicantModelBean.getEmailTo());
			logger.debug("subject=" + applicantModelBean.getSubject());
			logger.debug("messageText=" + applicantModelBean.getMessageText());
			
			List<uploadedfile> uploadedFiles = applicantModelBean.getUploadedFiles();

			for (UploadedFile uploadedFile : uploadedFiles) {
				logger.debug("uploadedFile=[{0}]", uploadedFile.getName());
			}
		}

		// Delete the uploaded files.
		try {
			
			List<uploadedfile> uploadedFiles = applicantModelBean.getUploadedFiles();
			
			emailSenderServiceBean.setTo(applicantModelBean.getEmailTo());
			emailSenderServiceBean.setSubject(applicantModelBean.getSubject());
			emailSenderServiceBean.setMessageBodyText(applicantModelBean.getMessageText());
			emailSenderServiceBean.setFiles(uploadedFiles);
			emailSenderServiceBean.sendEmail();
			
			emailSenderServiceBean.reset();
			
			for (UploadedFile uploadedFile : uploadedFiles) {
				uploadedFile.delete();
				logger.debug("Deleted file=[{0}]", uploadedFile.getName());
			}

			// Store the applicant's first name in JSF 2 Flash Scope so that it can be picked up
			// for use inside of confirmation.xhtml
			FacesContext facesContext = FacesContext.getCurrentInstance();
			facesContext.getExternalContext().getFlash().put("subject", applicantModelBean.getSubject());

			applicantModelBean.clearProperties();

			return "success";

		}
		catch (Exception e) {
			logger.error(e.getMessage(), e);
			FacesMessageUtil.addGlobalUnexpectedErrorMessage(FacesContext.getCurrentInstance());

			return "failure";
		}
	}

	public void setApplicantModelBean(ApplicantModelBean applicantModelBean) {

		// Injected via @ManagedProperty annotation
		this.applicantModelBean = applicantModelBean;
	}
	
	public void setEmailSenderServiceBean(EmailSenderServiceBean emailSenderServiceBean) {

		// Injected via @ManagedProperty annotation
		this.emailSenderServiceBean = emailSenderServiceBean;
	}

}
</uploadedfile></uploadedfile></uploadedfile></uploadedfile>


ApplicantModelBean.-

@ManagedBean(name = "applicantModelBean")
@ViewScoped
public class ApplicantModelBean implements Serializable {

	// serialVersionUID
	private static final long serialVersionUID = 7459628254337818761L;

	// Private Data Members
	private List<uploadedfile> uploadedFiles;
	private String emailTo;
	private String subject;
	private String messageText;

	public ApplicantModelBean() {
		clearProperties();
	}

	public void clearProperties() {
		uploadedFiles = new ArrayList<uploadedfile>();
		emailTo = null;
		subject = null;
		messageText = null;
	}
	
	public String getEmailTo() {
		return emailTo;
	}

	public void setEmailTo(String emailTo) {
		this.emailTo = emailTo;
	}

	public String getSubject() {
		return subject;
	}

	public void setSubject(String subject) {
		this.subject = subject;
	}

	public String getMessageText() {
		return messageText;
	}

	public void setMessageText(String messageText) {
		this.messageText = messageText;
	}

	public List<uploadedfile> getUploadedFiles() {
		return uploadedFiles;
	}

}
</uploadedfile></uploadedfile></uploadedfile>


It is important to say that I have removed any entry to Apache MyFaces in the pom.xml file
and inthe web.xml file as well.

Regards
Jose
thumbnail
Neil Griffin, geändert vor 11 Jahren.

RE: Attached files in an email client portlet, how to (Antwort)

Liferay Legend Beiträge: 2655 Beitrittsdatum: 27.07.05 Neueste Beiträge
Hi Jose,

Very glad to hear that you got it working. BTW, you might want to check out the MailEngine and/or MailServiceUtil classes for convenient APIs for sending emails from a Liferay-based portlet.

Neil
thumbnail
Juan Gonzalez, geändert vor 11 Jahren.

RE: Attached files in an email client portlet, how to (Antwort)

Liferay Legend Beiträge: 3089 Beitrittsdatum: 28.10.08 Neueste Beiträge
Hi Jose,

Just a note.

Why ApplicantBackingBean has View Scope? I see all attributes are transient, so in this case this bean is a "Controller" bean.

Probably you can change this to be @RequestScoped
thumbnail
Kyle Joseph Stiemann, geändert vor 11 Jahren.

RE: Attached files in an email client portlet, how to

Liferay Master Beiträge: 760 Beitrittsdatum: 14.01.13 Neueste Beiträge
Juan,
Thanks so much for pointing that out. It might be the case that Jose designed his application similar to our jsf2-portlet ApplicantBackingBean which is @ViewScoped. But the only reason that it is @ViewScoped is because of the commentsRendered property. I just talked it over with Neil, and we're going to change that pattern a little and introduce a @ViewScoped ApplicantViewBean for the commentsRendered property. That will allow us to change the scope of the ApplicantBackingBean to @RequestScoped.

We just created FACES-1543 in order to track this issue.

Thanks,
- Kyle
thumbnail
Juan Gonzalez, geändert vor 11 Jahren.

RE: Attached files in an email client portlet, how to

Liferay Legend Beiträge: 3089 Beitrittsdatum: 28.10.08 Neueste Beiträge
Yep, those "rendered" properties should be the only way (IMHO) of having a Managed Bean in View Scope (because of processing those values in RESTORE_VIEW phase).

ViewScope beans are used too much (sometimes people doesn't realize what's the impact following that practice). That's why many production apps becomes unusable after concurrent users growth.
thumbnail
Jose Alvarez de Lara, geändert vor 10 Jahren.

RE: Attached files in an email client portlet, how to

Junior Member Beiträge: 45 Beitrittsdatum: 10.12.12 Neueste Beiträge
Hi guys, thanks a lot for your replies.

Yes the reasson why the backing bean is @ViewScoped is beacause what Kyle says, I took it from your JSF2 Portlet example
released December 1, 2012,

JSF2 Portlet

Juan I am not an expert in JSF so any suggestion I should have it really glad emoticon

Thanks again,
Jose
thumbnail
Juan Gonzalez, geändert vor 10 Jahren.

RE: Attached files in an email client portlet, how to

Liferay Legend Beiträge: 3089 Beitrittsdatum: 28.10.08 Neueste Beiträge
My only suggestion at the moment would be not using @ViewScoped at any time. It should be used few times as possible and with few attributes in those beans.
thumbnail
Jose Alvarez de Lara, geändert vor 10 Jahren.

RE: Attached files in an email client portlet, how to

Junior Member Beiträge: 45 Beitrittsdatum: 10.12.12 Neueste Beiträge
Yes I will review my code and put it as you say.

Thanks,
jose