Chapter 20. Email

Seam now includes an optional component for templating and sending email.
Email support is provided by jboss-seam-mail.jar. This JAR contains the mail JSF controls, used to construct emails, and the mailSession manager component.
For a demonstration of the email support available in Seam, see the examples/mail project. This demonstrates proper packaging, and contains a number of currently-supported key features.
You can test your mail system with Seam's integration testing environment. See Section 35.3.4, “Integration Testing Seam Mail” for details.

20.1. Creating a message

Seam uses Facelets to template emails.
<m:message xmlns="http://www.w3.org/1999/xhtml"
           xmlns:m="http://jboss.com/products/seam/mail"
           xmlns:h="http://java.sun.com/jsf/html">
  
  <m:from name="Peter" address="peter@example.com" />
  <m:to name="#{person.firstname} #{person.lastname}">
    #{person.address}
  </m:to>
  <m:subject>Try out Seam!</m:subject>
  
  <m:body>
    <p><h:outputText value="Dear #{person.firstname}" />,</p>
    <p>You can try out Seam by visiting 
    <a href="http://labs.jboss.com/jbossseam">
      http://labs.jboss.com/jbossseam
      </a>.
    </p>
    <p>Regards,</p>
    <p>Pete</p>
  </m:body>
  
</m:message>
The <m:message> tag wraps the whole message, and tells Seam to start rendering an email. Inside the <m:message> tag, we use an <m:from> tag to specify the sender, a <m:to> tag to specify a recipient, and a <m:subject> tag. (Note that EL is used as it would be in a normal Facelet.)
The <m:body> tag wraps the body of the email. You can use regular HTML tags inside the body, as well as JSF components.
Once the m:message is rendered, the mailSession is called to send the email. To send your email, have Seam render the view:
@In(create=true)
private Renderer renderer;
    
public void send() {
    try {
        renderer.render("/simple.xhtml");
        facesMessages.add("Email sent successfully");
    } catch (Exception e) {
        facesMessages.add("Email sending failed: " + e.getMessage());
    }
}
If, for example, you entered an invalid email address, then an exception is thrown, caught and then displayed to the user.

20.1.1. Attachments

Seam supports most standard Java types when working with files, so it is easy to attach files to an email.
For example, to email the jboss-seam-mail.jar:
<m:attachment value="/WEB-INF/lib/jboss-seam-mail.jar"/>
Seam loads the file from the classpath and attaches it to the email. By default, this file is attached as jboss-seam-mail.jar, but you can change the attachment name by adding and editing the fileName attribute:
<m:attachment value="/WEB-INF/lib/jboss-seam-mail.jar" 
      fileName="this-is-so-cool.jar"/>
You can also attach a java.io.File, a java.net.URL:
<m:attachment value="#{numbers}"/>
Or a byte[] or a java.io.InputStream:
<m:attachment value="#{person.photo}" contentType="image/png"/>
For byte[] and java.io.InputStream, you will need to specify the MIME type of the attachment, since this information is not carried as part of the file.
You can attach a Seam-generated PDF, or any standard JSF view, by wrapping a <m:attachment> tag around your normal tags:
<m:attachment fileName="tiny.pdf"> 
  <p:document>
    A very tiny PDF
  </p:document> 
</m:attachment>
To attach a set of files — for example, a set of pictures loaded from a database — you can use a <ui:repeat>:
<ui:repeat value="#{people}" var="person"> 
  <m:attachment value="#{person.photo}" contentType="image/jpeg"
                fileName="#{person.firstname}_#{person.lastname}.jpg"/> 
</ui:repeat>
To display an attached image inline:
<m:attachment value="#{person.photo}" contentType="image/jpeg" 
              fileName="#{person.firstname}_#{person.lastname}.jpg" 
              status="personPhoto" disposition="inline" /> 
<img src="cid:#{personPhoto.contentId}" />
The cid:#{...} tag specifies that the attachments will be examined when attempting to locate the image. The cidContent-ID — must match.
You must declare the attachment before trying to access the status object.

20.1.2. HTML/Text alternative part

Although most mail readers support HTML, some do not. You can add a plain text alternative to your email body:
<m:body> 
  <f:facet name="alternative">
    Sorry, your email reader can not show our fancy email. Please go to 
    http://labs.jboss.com/jbossseam to explore Seam.
  </f:facet>
</m:body>

20.1.3. Multiple recipients

Often you will want to send an email to a group of recipients, such as your users. All recipient mail tags can be placed inside a <ui:repeat>:
<ui:repeat value="#{allUsers} var="user"> 
  <m:to name="#{user.firstname} #{user.lastname}" 
        address="#{user.emailAddress}"/> 
</ui:repeat>

20.1.4. Multiple messages

Sometimes — for example, during a password reset — you will need to send a slightly different message to each recipient. The best way to do this is to place the whole message inside a <ui:repeat>:
<ui:repeat value="#{people}" var="p">
  <m:message> 
    <m:from name="#{person.firstname} #{person.lastname}">
      #{person.address}
    </m:from> 
    <m:to name="#{p.firstname}">#{p.address}</m:to> 
    ... 
  </m:message> 
</ui:repeat>

20.1.5. Templating

The mail templating example shows that Facelets templating works with the Seam mail tags.
Our template.xhtml contains:
<m:message>
  <m:from name="Seam" address="do-not-reply@jboss.com" />
  <m:to name="#{person.firstname} #{person.lastname}">
    #{person.address}
  </m:to>
  <m:subject>#{subject}</m:subject>
  <m:body>
    <html>
      <body>
        <ui:insert name="body">
          This is the default body, specified by the template.
        </ui:insert>
      </body>
    </html>
  </m:body>
</m:message>
Our templating.xhtml contains:
<ui:param name="subject" value="Templating with Seam Mail"/> 
<ui:define name="body"> 
  <p>
    This example demonstrates that you can easily use 
    <i>facelets templating</i> in email!
  </p> 
</ui:define>
You can also use Facelets source tags in your email. These must be placed in a JAR in WEB-INF/lib because referencing the .taglib.xml from web.xml is not reliable when using Seam Mail. (When mail is sent asynchronously, Seam Mail cannot access the full JSF or Servlet context, so it does not acknowledge web.xml configuration parameters.)
To configure Facelets or JSF further when sending mail, you will need to override the Renderer component and perform the configuration programmatically. This should only be done by advanced users.

20.1.6. Internationalization

Seam supports sending internationalized messages. By default, Seam uses encoding provided by JSF, but this can be overridden on the template:
<m:message charset="UTF-8"> 
  ... 
</m:message>
The body, subject, and recipient and sender names are encoded. You will need to make sure that Facelets parses your page with the correct character set by setting the encoding of the template:
<?xml version="1.0" encoding="UTF-8"?>

20.1.7. Other Headers

Seam also provides support for some additional email headers. (See Section 20.4, “Tags”.) You can set the importance of the email, and ask for a read receipt:
<m:message xmlns:m="http://jboss.com/products/seam/mail" 
           importance="low" requestReadReceipt="true"/>
Otherwise, you can add any header to the message by using the <m:header> tag:
<m:header name="X-Sent-From" value="JBoss Seam"/>