Package com.qwertovsky.mailer

Source Code of com.qwertovsky.mailer.MessageContent

package com.qwertovsky.mailer;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.internet.ContentType;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.mail.internet.ParseException;
import javax.swing.text.html.parser.ParserDelegator;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import com.qwertovsky.mailer.errors.QwertoMailerException;


/**
* Message with content, content type, charset
* , contentTransferEncoding, subject and address 'From:'
*
* <p>For example:</p>
* <pre class="code">
* //simple text message
* MessageContent message = new MessageContent(
*   "Message text", "text/plain", "Subject", "utf-8");
* message.setAddressFrom("Company", "sender@company.com", "utf-8");</pre>
*
* <pre class="code">
* //html message with alternative part
* MessageContent message = new MessageContent(
*  "<html>HTML message</html>", "text/html", "Subject", "utf-8");
* message.setAlternativeText("Text message", "utf-8");
* message.setAddressFrom("Company", "sender@company.com", "utf-8");</pre>
*
* @author Qwertovsky
*/
public class MessageContent
{
  private Object content = null;
  private String contentType = null;
  private String subject = null;
  private InternetAddress addressFrom = null;
  private String charset = "UTF-8";
  private String contentTransferEncoding = "8bit";
 
  //--------------------------------------------
  /**
   * Create copy of MessageContent object
   * @param messageContent source object
   * @throws Exception
   * @throws NullPointerException MessageContent is null
   */
  public MessageContent (MessageContent messageContent)
    throws Exception, NullPointerException
  {
    Object newContent = messageContent.getContent();
    if(newContent instanceof String)
      this.content = new String((String) newContent);
    else if(newContent instanceof Multipart)
    {
      ContentType ct = new ContentType(((Multipart)newContent).getContentType());
      String subType = ct.getSubType();
      Multipart multipart = new MimeMultipart(subType);
      //add parts
      for(int i=0; i < ((Multipart)newContent).getCount();i++)
      {
        multipart.addBodyPart(((Multipart)newContent).getBodyPart(i));
      }
      this.content = multipart;
    }
    InternetAddress address = (InternetAddress) messageContent.getAddressFrom();
    try
    {
      this.addressFrom = new InternetAddress(address.getAddress(), address.getPersonal());
    } catch (UnsupportedEncodingException e)
    {
      // never
    }
    this.charset = new String(messageContent.getCharset());
    this.contentType = new String(messageContent.getContentType());
    this.contentTransferEncoding = new String(messageContent.getContentTransferEncoding());
    this.subject = new String(messageContent.getSubject());
  }
 
  //--------------------------------------------
  /**
   * Create message from EML file.<br />
   * Only content, content type and subject will be get from file.<br />
   * Not allow create message with no subject or with empty subject.
   * @param EMLFile file contains message in EML file format
   * @throws FileNotFoundException EML file not exists
   * @throws Exception
   * @throws NullPointerException EML file is null
   * @throws QwertoMailerException Subject can't be null or empty
   */
  public MessageContent(File EMLFile)
    throws QwertoMailerException
    , FileNotFoundException
    , NullPointerException
    , Exception
  {
    InputStream isEML = null;
    isEML = new FileInputStream(EMLFile);
    getMessageFromStream(isEML);
  }
 
  //--------------------------------------------
  /**
   * Create message from input stream of EML file.<br />
   * Only content, content type and subject will be get from file.<br />
   * Not allow create message with no subject or with empty subject.
   * @param EMLFileIStream input stream contains message in EML file format
   * @throws Exception
   * @throws QwertoMailerException Subject can't be null or empty
   */
  public MessageContent(InputStream EMLFileIStream)
    throws QwertoMailerException
    , Exception
  {
    getMessageFromStream(EMLFileIStream);
  }
 
  //--------------------------------------------
  private void getMessageFromStream(InputStream EMLFileIStream)
  throws QwertoMailerException
  , Exception
  {
    Session mailSession = Session.getDefaultInstance(new Properties(), null);
    Message message = new MimeMessage(mailSession, EMLFileIStream);
    content = message.getContent();
    contentType = message.getContentType();
    subject = message.getSubject();
    if(subject == null || subject.equals(""))
      throw new QwertoMailerException("Subject can't be null or empty");
    //get charset
    ContentType ct = new ContentType(contentType);
    charset = ct.getParameter("charset");
    if(charset == null)
      charset = "UTF-8";
  }
 
  //--------------------------------------------
  /**
   * Create message from text.<br />
   * Not allow create message with no subject or with empty subject
   * @param content text
   * @param contentType Mime type of content ('text/plain' or 'text/html')
   * @param subject
   * @param charset encoding of content (default is "utf-8")
   * @throws QwertoMailerException if content is null or content is empty text line
   *   <br />- if content type is null or content type is empty text line or error parse,
   *  message "Bad ContentType"
   *  <br />- if subject is null or subject is empty text line, message "Bad subject"
   */
  public MessageContent(String content, String contentType, String subject, String charset)
    throws QwertoMailerException
  {
    //not allow content with no body parts
    if(content == null || content.equals(""))
      throw new QwertoMailerException("Content can't be null or empty");
    this.content = content;
   
    //not allow message with no subject
    if(subject == null || subject.equals(""))
      throw new QwertoMailerException("Subject can't be null or empty");
    this.subject = subject;
   
    //set default charset
    if(charset == null || charset.length() == 0)
      charset = "utf-8";
    this.charset = charset;
   
    if(contentType == null || contentType.length() == 0)
      throw new QwertoMailerException("Content type can't be null or empty");
   
    try
    {
      ContentType ct = new ContentType(contentType);
      this.contentType = ct.getBaseType() + "; charset=" + charset;
      ct = new ContentType(this.contentType);
    } catch (ParseException pe)
    {
      //specify that the problem relates to the ContentType
      throw new QwertoMailerException("Bad ContentType: " + pe.getMessage());
    }
  }
 
  //--------------------------------------------
  /**
   * Return EML message as byte array
   * @throws Exception error create message from content
   */
  public byte[] toByteArray()
  throws Exception
  {
    ByteArrayOutputStream os = new ByteArrayOutputStream();
   
    Session session = Session.getDefaultInstance(new Properties(), null);
    MimeMessage mimeMessage = new MimeMessage(session);
    mimeMessage.setFrom(addressFrom);
    mimeMessage.setContent(content, contentType);
    mimeMessage.setSubject(subject, charset);
    mimeMessage.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
   
    mimeMessage.writeTo(os);
    byte[] byteArray = os.toByteArray();
    return byteArray;
  }
 
  //--------------------------------------------
  /**
   * Set subject
   * <br />Not allow null subject or empty subject
   * @param subject
   * @throws QwertoMailerException Subject can't be null or empty
   */
  public void setSubject(String subject) throws QwertoMailerException
  {
    if(subject == null || subject.equals(""))
      throw new QwertoMailerException("Subject can't be null or empty");
    this.subject = subject;
  }
  //--------------------------------------------
  /**
   * Specify address in field From:
   * @param person display name
   * @param email email address
   * @param charset encoding
   * @throws QwertoMailerException email is null or email is empty
   * @throws Exception if the address isn't valid
   * @throws UnsupportedEncodingException
   */
  public void setAddressFrom(String person, String email, String charset)
    throws QwertoMailerException
    , Exception
    , UnsupportedEncodingException
  {
    if(email == null || email.length() == 0)
      throw new QwertoMailerException ("Email in FROM can't be null or empty");
    addressFrom = new InternetAddress(email, person, charset);
    addressFrom.validate();
  }
  //--------------------------------------------
  /**
   * Add files to message
   * @param attachments list of files
   * @throws Exception
   * @throws FileNotFoundException
   * @throws IOException if an I/O error occurs
   */
  public void addAttachments(List<File> attachments)
    throws Exception, FileNotFoundException, IOException
 
  {
    if(attachments == null)
      return;
   
    //create new attachment parts
    List<MimeBodyPart> attachmentParts = new ArrayList<MimeBodyPart>(attachments.size());
    for(File attachment:attachments)
    {
      MimeBodyPart bodyPart = new MimeBodyPart();
      DataSource source = new FileDataSource(attachment);
      bodyPart.setDataHandler(new DataHandler(source));
      String filename = null;
      try
      {
        filename = MimeUtility.encodeText(attachment.getName(),charset, null);
        String mimeType = Files.probeContentType(attachment.toPath());
        bodyPart.setHeader("Content-Type", mimeType + "; name=\"" + filename+"\"");
        bodyPart.setFileName(filename);
      } catch (UnsupportedEncodingException e)
      {
        filename = attachment.getName();
      }
      attachmentParts.add(bodyPart);
    }
   
    if(content instanceof Multipart
        && ((Multipart)content).getContentType().startsWith("multipart/mixed"))
    {
      //add attachments to end
      for(MimeBodyPart bodyPart: attachmentParts)
      {
        ((Multipart)content).addBodyPart(bodyPart);
      }
    }
    else
    {
      //create part with type multipart/mixed
      Multipart multipart = new MimeMultipart();
      //add old content
      if(content instanceof Multipart
          && ((Multipart)content).getContentType().startsWith("multipart/alternative"))
      {
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setContent(content,contentType);
        multipart.addBodyPart(bodyPart);
      }
      else
      {
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setContent(content,contentType);
        bodyPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
        bodyPart.setHeader("Content-Type", contentType);
        multipart.addBodyPart(bodyPart);
      }
      //add attachments to end of message
      for(MimeBodyPart bodyPart: attachmentParts)
      {
        multipart.addBodyPart(bodyPart);
      }
      content = multipart;
      contentType = ((Multipart)content).getContentType();
    }
  }
  //--------------------------------------------
  /**
   * Attach file to message
   * @param attachment
   * @throws Exception
   * @throws FileNotFoundException
   * @throws IOException if an I/O error occurs
   */
  public void addAttachment(File attachment)
    throws Exception, FileNotFoundException, IOException
  {
    List<File> attachments = new ArrayList<File>(1);
    attachments.add(attachment);
    addAttachments(attachments);
  }
  //--------------------------------------------
  /**
   * Add inline attachment to message<br />
   * Change html content to multipart/related.<br />
   * Replace path in 'src'-attribute to "cid:content-id"<br />
   * Return &lt;content-id&gt;
   * @param path file path from image attribute 'src' (&lt;img src="<b>path</b>" /&gt;)
   * @return Content-ID of attachment with &lt; &gt;
   * @throws Exception
   * @throws IOException
   * @throws QwertoMailerException Inline image url is null or empty
   */
  protected String addInlineAttachment(String path)
    throws Exception, IOException, QwertoMailerException
  {
    if(path == null || path.length() == 0)
      throw new QwertoMailerException("Inline image url can't be null or empty");
    if(content instanceof Multipart
        && ((Multipart)content).getContentType().startsWith("multipart/mixed"))
    {
      //get and replace html part of message
      Object body = ((Multipart)content).getBodyPart(0).getContent();
      if(body instanceof Multipart
          && ((Multipart)body).getContentType().startsWith("multipart/alternative"))
      {
        //get main part (html or related)
        Object mainPart = ((Multipart)body).getBodyPart(1).getContent();
        if(mainPart instanceof Multipart)
        {
          /*
           * -mixed
           * \-alternative (body)
           *     \-text
           *     |-related (mainPart)
           *       \-html
           *       |-attachment
           * |-attachments
           */
         
          //add attachment
          MimeBodyPart attachPart = new MimeBodyPart();
          File attachment = new File(path);
          DataSource source = new FileDataSource(attachment);
          attachPart.setDataHandler(new DataHandler(source));
          attachPart.setFileName(attachment.getName());
          attachPart.setDisposition(MimeBodyPart.INLINE);
          String mimeType = Files.probeContentType(attachment.toPath());
          attachPart.setHeader("Content-Type",mimeType);
          attachPart.setContentID("<" + attachment.getName()
              + "." + attachPart.hashCode() +"."+ System.currentTimeMillis() +">");
          ((Multipart)mainPart).addBodyPart(attachPart);
          //replace html
          String html = (String)  ((Multipart)mainPart).getBodyPart(0).getContent();
          String cid = attachPart.getContentID();
          cid = cid.substring(1, cid.length() - 1);
          html = html.replace(path, "cid:" + cid);
          MimeBodyPart htmlPart = new MimeBodyPart();
          htmlPart.setContent(html, ((Multipart)mainPart).getBodyPart(0).getContentType());
          htmlPart.setHeader("Content-Type", ((Multipart)mainPart).getBodyPart(0).getContentType());
          htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
          ((Multipart)mainPart).removeBodyPart(0);
          ((Multipart)mainPart).addBodyPart(htmlPart, 0);
          //replace related
          MimeBodyPart bodyPart = new MimeBodyPart();
          bodyPart.setContent(((Multipart)mainPart));
          ((Multipart)body).removeBodyPart(1);
          ((Multipart)body).addBodyPart(bodyPart);
         
          //replace body
          ((Multipart)content).removeBodyPart(0);
          bodyPart = new MimeBodyPart();
          bodyPart.setContent(((Multipart)body));
          ((Multipart)content).addBodyPart(bodyPart, 0);
         
          return attachPart.getContentID();
        }
        else
        {
          /*
           * -mixed
           * \-alternative (body)
           *     \-text
           *     |-html (will be changed to related)
           * |-attachments
           */
          //create new alternative
          Multipart alternative = new MimeMultipart("alternative");
          //add palin part
          alternative.addBodyPart(((Multipart)body).getBodyPart(0));
         
          //get and replace html part to multipart/related
          //create multipart/related
          Multipart related = new MimeMultipart("related");
          //add attachment
          MimeBodyPart attachPart = new MimeBodyPart();
          File attachment = new File(path);
          DataSource source = new FileDataSource(attachment);
          attachPart.setDataHandler(new DataHandler(source));
          attachPart.setFileName(attachment.getName());
          attachPart.setDisposition(MimeBodyPart.INLINE);
          String mimeType = Files.probeContentType(attachment.toPath());
          attachPart.setHeader("Content-Type",mimeType);
          attachPart.setContentID("<" + attachment.getName()
              + "." + attachPart.hashCode() +"."+ System.currentTimeMillis() +">");
          related.addBodyPart(attachPart);
          //add html
          String html = (String)  ((Multipart)body).getBodyPart(1).getContent();
          String cid = attachPart.getContentID();
          cid = cid.substring(1, cid.length() - 1);
          html = html.replace(path, "cid:" + cid);
          MimeBodyPart htmlPart = new MimeBodyPart();
          htmlPart.setContent(html, ((Multipart)body).getBodyPart(1).getContentType());
          htmlPart.setHeader("Content-Type", ((Multipart)body).getBodyPart(1).getContentType());
          htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
          related.addBodyPart(htmlPart, 0);
          //add related to alternative
          MimeBodyPart bodyPart = new MimeBodyPart();
          bodyPart.setContent(related);
          alternative.addBodyPart(bodyPart);
         
          //replace body
          ((Multipart)content).removeBodyPart(0);
          bodyPart = new MimeBodyPart();
          bodyPart.setContent(alternative);
          ((Multipart)content).addBodyPart(bodyPart, 0);
         
          return attachPart.getContentID();
        }
      }
      else if(body instanceof Multipart
          && ((Multipart)body).getContentType().startsWith("multipart/related"))
      {
        /*
         * -mixed
         * \-related (body)
         *     \-html
         *     |-attachment
         * |-attachments
         */
        //add attachment
        MimeBodyPart attachPart = new MimeBodyPart();
        File attachment = new File(path);
        DataSource source = new FileDataSource(attachment);
        attachPart.setDataHandler(new DataHandler(source));
        attachPart.setFileName(attachment.getName());
        attachPart.setDisposition(MimeBodyPart.INLINE);
        String mimeType = Files.probeContentType(attachment.toPath());
        attachPart.setHeader("Content-Type",mimeType);
        attachPart.setContentID("<" + attachment.getName()
            + "." + attachPart.hashCode() +"."+ System.currentTimeMillis() +">");
        ((Multipart)body).addBodyPart(attachPart);
        //replace html
        String html = (String) ((Multipart)body).getBodyPart(0).getContent();;
        String cid = attachPart.getContentID();
        cid = cid.substring(1, cid.length() - 1);
        html = html.replace(path, "cid:" + cid);
        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent(html, ((Multipart)body).getBodyPart(0).getContentType());
        htmlPart.setHeader("Content-Type", ((Multipart)body).getBodyPart(0).getContentType());
        htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
        ((Multipart)body).removeBodyPart(0);
        ((Multipart)body).addBodyPart(htmlPart, 0);
       
        //replace body
        ((Multipart)content).removeBodyPart(0);
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setContent(((Multipart)body));
        ((Multipart)content).addBodyPart(bodyPart, 0);
       
        return attachPart.getContentID();
      }
      else
      {
        /*
         * -mixed
         * \-html (body)(will be changed to related)
         * |-attachments
         */
        //create multipart/related
        Multipart related = new MimeMultipart("related");
        //add attachment
        MimeBodyPart attachPart = new MimeBodyPart();
        File attachment = new File(path);
        DataSource source = new FileDataSource(attachment);
        attachPart.setDataHandler(new DataHandler(source));
        attachPart.setFileName(attachment.getName());
        attachPart.setDisposition(MimeBodyPart.INLINE);
        String mimeType = Files.probeContentType(attachment.toPath());
        attachPart.setHeader("Content-Type",mimeType);
        attachPart.setContentID("<" + attachment.getName()
            + "." + attachPart.hashCode() +"."+ System.currentTimeMillis() +">");
        related.addBodyPart(attachPart);
        //add html
        String html = (String) ((Multipart)content).getBodyPart(0).getContent();
        String cid = attachPart.getContentID();
        cid = cid.substring(1, cid.length() - 1);
        html = html.replace(path, "cid:" + cid);
        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent(html, ((Multipart)content).getBodyPart(0).getContentType());
        htmlPart.setHeader("Content-Type", ((Multipart)content).getBodyPart(0).getContentType());
        htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
        related.addBodyPart(htmlPart, 0);
       
        //replace body
        ((Multipart)content).removeBodyPart(0);
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setContent(related);
        ((Multipart)content).addBodyPart(bodyPart, 0);
       
        return attachPart.getContentID();
      }
    }
    else
    {
      if(content instanceof Multipart
          && ((Multipart)content).getContentType().startsWith("multipart/alternative"))
      {
        //get and replace html part of message
        Object body = ((Multipart)content).getBodyPart(1).getContent();
        if(body instanceof Multipart)
        {
          /*
           * -alternative (content)
           * \-text
           * |-related (body)
           *     \-html
           *     |-attachment
           */
          //add attachment
          MimeBodyPart attachPart = new MimeBodyPart();
          File attachment = new File(path);
          DataSource source = new FileDataSource(attachment);
          attachPart.setDataHandler(new DataHandler(source));
          attachPart.setFileName(attachment.getName());
          attachPart.setDisposition(MimeBodyPart.INLINE);
          String mimeType = Files.probeContentType(attachment.toPath());
          attachPart.setHeader("Content-Type",mimeType);
          attachPart.setContentID("<" + attachment.getName()
              + "." + attachPart.hashCode() +"."+ System.currentTimeMillis() +">");
          ((Multipart)body).addBodyPart(attachPart);
          //replace html
          String html = (String) ((Multipart)body).getBodyPart(0).getContent();
          String cid = attachPart.getContentID();
          cid = cid.substring(1, cid.length() - 1);
          html = html.replace(path, "cid:" + cid);
          MimeBodyPart htmlPart = new MimeBodyPart();
          htmlPart.setContent(html, ((Multipart)body).getBodyPart(0).getContentType());
          htmlPart.setHeader("Content-Type", ((Multipart)body).getBodyPart(0).getContentType());
          htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
          ((Multipart)body).removeBodyPart(0);
          ((Multipart)body).addBodyPart(htmlPart, 0);
          //replace related
          ((Multipart)content).removeBodyPart(1);
          MimeBodyPart relatedPart = new MimeBodyPart();
          relatedPart.setContent((Multipart) body);
          ((Multipart)content).addBodyPart(relatedPart, 1);
         
          return attachPart.getContentID();
        }
        else
        {
          /*
           * -alternative (content)
           * \-text
           * |-html
           */
          //get and replace html part to multipart/related
          //create multipart/related
          Multipart related = new MimeMultipart("related");
          //add attachment
          MimeBodyPart attachPart = new MimeBodyPart();
          File attachment = new File(path);
          DataSource source = new FileDataSource(attachment);
          attachPart.setDataHandler(new DataHandler(source));
          attachPart.setFileName(attachment.getName());
          attachPart.setDisposition(MimeBodyPart.INLINE);
          String mimeType = Files.probeContentType(attachment.toPath());
          attachPart.setHeader("Content-Type",mimeType);
          attachPart.setContentID("<" + attachment.getName()
              + "." + attachPart.hashCode() +"."+ System.currentTimeMillis() +">");
          related.addBodyPart(attachPart);
          //add html
          String html = (String) ((Multipart)content).getBodyPart(1).getContent();
          String cid = attachPart.getContentID();
          cid = cid.substring(1, cid.length() - 1);
          html = html.replace(path, "cid:" + cid);
          MimeBodyPart htmlPart = new MimeBodyPart();
          htmlPart.setContent(html, ((Multipart)content).getBodyPart(1).getContentType());
          htmlPart.setHeader("Content-Type", ((Multipart)content).getBodyPart(1).getContentType());
          htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
          related.addBodyPart(htmlPart, 0);
         
          //replace html part
          ((Multipart)content).removeBodyPart(1);
          MimeBodyPart bodyPart = new MimeBodyPart();
          bodyPart.setContent(related);
          ((Multipart)content).addBodyPart(bodyPart);
         
          return attachPart.getContentID();
        }
      }
      else if(content instanceof Multipart
          && ((Multipart)content).getContentType().startsWith("multipart/related"))
      {
        /*
         * -related (content)
         * \-html
         * |-attachment
         */
        //add attachment
        MimeBodyPart attachPart = new MimeBodyPart();
        File attachment = new File(path);
        DataSource source = new FileDataSource(attachment);
        attachPart.setDataHandler(new DataHandler(source));
        attachPart.setFileName(attachment.getName());
        attachPart.setDisposition(MimeBodyPart.INLINE);
        String mimeType = Files.probeContentType(attachment.toPath());
        attachPart.setHeader("Content-Type",mimeType);
        attachPart.setContentID("<" + attachment.getName()
            + "." + attachPart.hashCode() +"."+ System.currentTimeMillis() +">");
        ((Multipart)content).addBodyPart(attachPart);
        //replace html
        String html = (String) ((Multipart)content).getBodyPart(0).getContent();
        String cid = attachPart.getContentID();
        cid = cid.substring(1, cid.length() - 1);
        html = html.replace(path, "cid:" + cid);
        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent(html, ((Multipart)content).getBodyPart(0).getContentType());
        htmlPart.setHeader("Content-Type", ((Multipart)content).getBodyPart(0).getContentType());
        htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
        ((Multipart)content).removeBodyPart(0);
        ((Multipart)content).addBodyPart(htmlPart, 0);
       
        return attachPart.getContentID();
      }
      else
      {
        /*
         * -html (content)
         */
        //create multipart/related
        Multipart related = new MimeMultipart("related");
        //add attachment
        MimeBodyPart attachPart = new MimeBodyPart();
        File attachment = new File(path);
        DataSource source = new FileDataSource(attachment);
        attachPart.setDataHandler(new DataHandler(source));
        attachPart.setFileName(attachment.getName());
        attachPart.setDisposition(MimeBodyPart.INLINE);
        String mimeType = Files.probeContentType(attachment.toPath());
        attachPart.setHeader("Content-Type",mimeType);
        attachPart.setContentID("<" + attachment.getName()
            + "." + attachPart.hashCode() +"."+ System.currentTimeMillis() +">");
        related.addBodyPart(attachPart);
        //add html
        String html = (String) content;
        String cid = attachPart.getContentID();
        cid = cid.substring(1, cid.length() - 1);
        html = html.replace(path, "cid:" + cid);
        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent(html, contentType);
        htmlPart.setHeader("Content-Type", contentType);
        htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
        related.addBodyPart(htmlPart, 0);
       
        content = related;
        contentType = related.getContentType();
        return attachPart.getContentID();
      }
    }
     
  }
  //--------------------------------------------
  /**
   * Change html part of message to multipart/related part.
   * <br />Files must be available by path, that is specified in attribute SRC in tag IMG.
   * @return list of file path, that was specified in html part
   * @throws Exception
   * @throws IOException
   * @throws QwertoMailerException
   */
  public List<String> setRelated()
    throws Exception, IOException, QwertoMailerException
  {
    List<String> paths = null;
    //get html part content
    String html = null;
    if(content instanceof Multipart
        && ((Multipart)content).getContentType().startsWith("multipart/mixed"))
    {
      Object body = ((Multipart)content).getBodyPart(0).getContent();
      if(body instanceof Multipart
          && ((Multipart)body).getContentType().startsWith("multipart/alternative"))
      {
        /*
         * -alternative (body)
         *   \-text
         *   |
         */
        Object mainPart = ((Multipart)body).getBodyPart(1).getContent();
        if(mainPart instanceof Multipart
            && ((Multipart)mainPart).getContentType().startsWith("multipart/related"))
        {
          /*
           * -alternative (body)
           *   \-text
           *   |-related (mainPart)
           *     \-html
           *     |-attachments
           */
          html = (String) ((Multipart)mainPart).getBodyPart(0).getContent();
        }
        else
        {
          /*
           * -alternative (content)
           *   \-text
           *   |-html (mainPart)
           */
          html = (String) mainPart;
        }
      }
      else
      {
        if(body instanceof Multipart
            && ((Multipart)body).getContentType().startsWith("multipart/related"))
        {
          /*
           * -related (body)
           *   \-html
           *   |-attachments
           */
          html = (String) ((Multipart)body).getBodyPart(0).getContent();
        }
        else
        {
          /*
           * -html (body)
           */
          html = (String) body;
        }
      }
    }
    else
    {
      if(content instanceof Multipart
          && ((Multipart)content).getContentType().startsWith("multipart/alternative"))
      {
        /*
         * -alternative (content)
         *   \-text
         *   |
         */
        Object mainPart = ((Multipart)content).getBodyPart(1).getContent();
        if(mainPart instanceof Multipart
            && ((Multipart)mainPart).getContentType().startsWith("multipart/related"))
        {
          /*
           * -alternative (content)
           *   \-text
           *   |-related (mainPart)
           *     \-html
           *     |-attachments
           */
          html = (String) ((Multipart)mainPart).getBodyPart(0).getContent();
        }
        else
        {
          /*
           * -alternative (content)
           *   \-text
           *   |-html
           */
          html = (String) mainPart;
        }
      }
      else
      {
        if(content instanceof Multipart
            && ((Multipart)content).getContentType().startsWith("multipart/related"))
        {
          /*
           * -related (content)
           *   \-html
           *   |-attachments
           */
          html = (String) ((Multipart)content).getBodyPart(0).getContent();
        }
        else
        {
          /*
           * -html (content)
           */
          html = (String) content;
        }
      }
    }
   
    //get all file paths from html part
    ParserDelegator htmlParser = new ParserDelegator();
    ImageCallback callback = new ImageCallback();
    StringReader reader = new StringReader(html);
    htmlParser.parse(reader, callback, true);
    paths = callback.getPathList();

    //create multipart/related part
    for(String path:paths)
    {
      addInlineAttachment(path);
    }
    return paths;
  }
  //--------------------------------------------
  /**
   * Add alternative text for email clients, that do not support HTML message
   * @param text plain text
   * @param charset encoding
   * @throws Exception
   */
  public void setAlternativeText(String text, String charset)
  throws Exception
  {
    /*
     * Message have the following format:
     * without attachment:
     *     (-body (multipart/related or text)
     *     or
     *     -multipart/alternative
     *       -alternative text
     *       -body (multipart/related or text)
     *     )
     * with attachment:
     *     (-multipart/mixed
     *       (-body (multipart/related or text)
     *       or
     *       -multipart/alternative
     *         -alternative text
     *         -body (multipart/related or text)
     *       )
     *       -attachment
     *     )
     *
     * If message is mixed, the first is the body then attachments.
     * If body is with alternative text, the first is alternative text then main body
     */ 
    if(content instanceof Multipart
        && ((Multipart)content).getContentType().startsWith("multipart/mixed"))
    {
      Multipart mixed = ((Multipart)content);
      //get first part: body or multipart/alternative
      Object body = mixed.getBodyPart(0).getContent();
      if(body instanceof Multipart
          && ((Multipart)body).getContentType().startsWith("multipart/alternative"))
      {
        //create new alternative
        Multipart multipart = new MimeMultipart("alternative");
        //create new plain part
        MimeBodyPart plain = new MimeBodyPart();
        plain.setText(text, charset);
        plain.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
        multipart.addBodyPart(plain);
        //add main body part
        multipart.addBodyPart(((Multipart)body).getBodyPart(1));
        //delete old alternative - the first part of mixed message
        ((Multipart)content).removeBodyPart(0);
        //add new alternative in first position before attachments
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setContent(multipart);
        ((Multipart)content).addBodyPart(bodyPart, 0);
      }
      else //body with no alternative text
      {
        //create new alternative
        Multipart multipartAlt = new MimeMultipart("alternative");
        //add plain alternative text
        MimeBodyPart plain = new MimeBodyPart();
        plain.setText(text, charset);
        plain.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
        multipartAlt.addBodyPart(plain);
        //add main body part
        multipartAlt.addBodyPart(((Multipart)content).getBodyPart(0));
        //replace main body of message to multipart/alternative body
        mixed.removeBodyPart(0);
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setContent(multipartAlt, "multipart/alternative");
        mixed.addBodyPart(bodyPart, 0);
        content = mixed;
      }
    }
    else if (content instanceof Multipart
        && ((Multipart)content).getContentType().startsWith("multipart/alternative"))
    {
      //replace old alternative text to new
      MimeBodyPart plain = new MimeBodyPart();
      plain.setText(text, charset);
      plain.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
      ((Multipart)content).removeBodyPart(0);
      ((Multipart)content).addBodyPart(plain, 0);
    }
    else //message with no attachments and body with no alternative text
    {
      //create new multipart/alternative message
      Multipart multipart = new MimeMultipart("alternative");
      MimeBodyPart plain = new MimeBodyPart();
      plain.setText(text, charset);
      plain.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
      multipart.addBodyPart(plain);
      MimeBodyPart bodyPart = new MimeBodyPart();
      bodyPart.setContent(content, contentType);
      multipart.addBodyPart(bodyPart);
      content = multipart;
      contentType = ((Multipart)content).getContentType();
    }
     
  }
 
  //--------------------------------------------
  public void setContentTransferEncoding(String contentTransferEncoding)
  {
    if(contentTransferEncoding != null && contentTransferEncoding.length() != 0)
      this.contentTransferEncoding = contentTransferEncoding;
  }
 
  //--------------------------------------------
  public String getCharset()
  {
    return charset;
  }
 
  //--------------------------------------------
  public Object getContent()
  {
    return content;
  }
 
  //--------------------------------------------
  public String getContentType()
  {
    return contentType;
  }
 
  //--------------------------------------------
  public String getSubject()
  {
    return subject;
  }
 
  //--------------------------------------------
  public Address getAddressFrom()
  {
    return addressFrom;
  }
 
  //--------------------------------------------
  public String getContentTransferEncoding()
  {
    return contentTransferEncoding;
  }

  //--------------------------------------------
  /**
   * Put inline parameters in message
   * <br /> If header specified (ex. $header), but relevant parameter is null
   *  - $header will be replaced to empty string
   * 
   * @param headers array of parameter's headers
   * @param parameters array of parameters
   * @throws IOException
   * @throws QwertoMailerException Headers can't be null or have length equal to 0,
   * <br />Parameters can't be null or have length equal to 0
   * <br />Parameters must be not less then headers
   */
  public void setParameters(String[] headers, String[] parameters)
    throws Exception
    , QwertoMailerException
  {
    if(headers == null || headers.length == 0)
      throw new QwertoMailerException("Headers can't be null or have length equal to 0");
    if(parameters == null || parameters.length == 0)
      throw new QwertoMailerException("Parameters can't be null or have length equal to 0");
    if(parameters.length < headers.length)
      throw new QwertoMailerException("Parameters must be not less then headers");
   
    //from arrays to map
    Map<String, String> parameterMap = new HashMap<String, String>(headers.length);
    for(int i = 0; i < headers.length; i++)
    {
      if(headers[i] == null || headers[i].length() == 0)
        continue;
      parameterMap.put(headers[i], parameters[i]);
    }
   
    setParameters(parameterMap);
   
  }
 
  //--------------------------------------------
  /**
   * Put inline parameters in message
   * <br /> If header specified (ex. $header), but relevant parameter is null
   *  - $header will be replaced to empty string
   * @param parameters map of parameters
   * @throws IOException
   * @throws QwertoMailerException Parameters can't be null or have length equal to 0
   *
   */
  public void setParameters(Map<String, String> parameters)
    throws Exception
    , QwertoMailerException
  {
    if(parameters == null || parameters.size() == 0)
      throw new QwertoMailerException("Parameters can't be null or have length equal to 0");
   
    Set<String> headers = parameters.keySet();
   
    VelocityContext context = new VelocityContext();
    for(String header:headers)
    { 
      if(header == null || header.length() == 0)
        continue;
      String parameter = parameters.get(header);
      if(parameter == null)
        parameter = "";
      context.put(header, parameter);
    }
   
    if(content instanceof Multipart
        && ((Multipart)content).getContentType().startsWith("multipart/mixed"))
    {
      //get and replace html part of message
      Object body = ((Multipart)content).getBodyPart(0).getContent();
      if(body instanceof Multipart
          && ((Multipart)body).getContentType().startsWith("multipart/alternative"))
      {
        //get alternative text
        BodyPart altPart = ((Multipart)body).getBodyPart(0);
        String alterText = (String) altPart.getContent();
        StringWriter alterTextWriter = new StringWriter();
        Velocity.evaluate(context, alterTextWriter, "message body", alterText);
        alterTextWriter.flush();
        alterTextWriter.close();
        alterText = alterTextWriter.toString();
        ContentType ct = new ContentType(altPart.getContentType());
        String alterTextCharset = ct.getParameter("charset");
       
        //get main part (html or related)
        Object mainPart = ((Multipart)body).getBodyPart(1).getContent();
        if(mainPart instanceof Multipart)
        {
          /*
           * -mixed
           * \-alternative (body)
           *     \-text
           *     |-related (mainPart)
           *       \-html
           *       |-attachment
           * |-attachments
           */
         
          //replace html
          String html = (String)  ((Multipart)mainPart).getBodyPart(0).getContent();
          StringWriter mailBody = new StringWriter();
          Velocity.evaluate(context, mailBody, "message body", html);
          mailBody.flush();
          mailBody.close();
          html = mailBody.toString();
          MimeBodyPart htmlPart = new MimeBodyPart();
          htmlPart.setContent(html, ((Multipart)mainPart).getBodyPart(0).getContentType());
          htmlPart.setHeader("Content-Type", ((Multipart)mainPart).getBodyPart(0).getContentType());
          htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
          ((Multipart)mainPart).removeBodyPart(0);
          ((Multipart)mainPart).addBodyPart(htmlPart, 0);
          //replace related
          MimeBodyPart bodyPart = new MimeBodyPart();
          bodyPart.setContent(((Multipart)mainPart));
          ((Multipart)body).removeBodyPart(1);
          ((Multipart)body).addBodyPart(bodyPart);
         
          //replace body
          ((Multipart)content).removeBodyPart(0);
          bodyPart = new MimeBodyPart();
          bodyPart.setContent(((Multipart)body));
          ((Multipart)content).addBodyPart(bodyPart, 0);
        }
        else
        {
          /*
           * -mixed
           * \-alternative (body)
           *     \-text
           *     |-html
           * |-attachments
           */
          //replace html
          String html = (String)  ((Multipart)body).getBodyPart(1).getContent();
          StringWriter mailBody = new StringWriter();
          Velocity.evaluate(context, mailBody, "message body", html);
          mailBody.flush();
          mailBody.close();
          html = mailBody.toString();
          MimeBodyPart htmlPart = new MimeBodyPart();
          htmlPart.setContent(html, ((Multipart)body).getBodyPart(1).getContentType());
          htmlPart.setHeader("Content-Type", ((Multipart)body).getBodyPart(1).getContentType());
          htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
         
          //replace html
          ((Multipart)body).removeBodyPart(1);
          ((Multipart)body).addBodyPart(htmlPart, 1);
         
          //replace body
          ((Multipart)content).removeBodyPart(0);
          MimeBodyPart bodyPart = new MimeBodyPart();
          bodyPart.setContent(((Multipart)body));
          ((Multipart)content).addBodyPart(bodyPart, 0);
        }
       
        if(alterTextCharset != null)
          setAlternativeText(alterText, alterTextCharset);
        else
          setAlternativeText(alterText, charset);
      }
      else if(body instanceof Multipart
          && ((Multipart)body).getContentType().startsWith("multipart/related"))
      {
        /*
         * -mixed
         * \-related (body)
         *     \-html
         *     |-attachment
         * |-attachments
         */
       
        //replace html
        String html = (String) ((Multipart)body).getBodyPart(0).getContent();;
        StringWriter mailBody = new StringWriter();
        Velocity.evaluate(context, mailBody, "message body", html);
        mailBody.flush();
        mailBody.close();
        html = mailBody.toString();
        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent(html, ((Multipart)body).getBodyPart(0).getContentType());
        htmlPart.setHeader("Content-Type", ((Multipart)body).getBodyPart(0).getContentType());
        htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
        ((Multipart)body).removeBodyPart(0);
        ((Multipart)body).addBodyPart(htmlPart, 0);
       
        //replace body
        ((Multipart)content).removeBodyPart(0);
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setContent(((Multipart)body));
        ((Multipart)content).addBodyPart(bodyPart, 0);
      }
      else
      {
        /*
         * -mixed
         * \-html (body)
         * |-attachments
         */
       
        //replace html
        String html = (String) ((Multipart)content).getBodyPart(0).getContent();
        StringWriter mailBody = new StringWriter();
        Velocity.evaluate(context, mailBody, "message body", html);
        mailBody.flush();
        mailBody.close();
        html = mailBody.toString();
        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent(html, ((Multipart)content).getBodyPart(0).getContentType());
        htmlPart.setHeader("Content-Type", ((Multipart)content).getBodyPart(0).getContentType());
        htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
       
        ((Multipart)content).removeBodyPart(0);
        ((Multipart)content).addBodyPart(htmlPart, 0);
      }
    }
    else
    {
      if(content instanceof Multipart
          && ((Multipart)content).getContentType().startsWith("multipart/alternative"))
      {
        //get alternative text
        BodyPart altPart = ((Multipart)content).getBodyPart(0);
        String alterText = (String) altPart.getContent();
        StringWriter alterTextWriter = new StringWriter();
        Velocity.evaluate(context, alterTextWriter, "message body", alterText);
        alterTextWriter.flush();
        alterTextWriter.close();
        alterText = alterTextWriter.toString();
        ContentType ct = new ContentType(altPart.getContentType());
        String alterTextCharset = ct.getParameter("charset");
       
        //get and replace html part of message
        Object body = ((Multipart)content).getBodyPart(1).getContent();
        if(body instanceof Multipart)
        {
          /*
           * -alternative (content)
           * \-text
           * |-related (body)
           *     \-html
           *     |-attachment
           */
         
          //replace html
          String html = (String) ((Multipart)body).getBodyPart(0).getContent();
          StringWriter mailBody = new StringWriter();
          Velocity.evaluate(context, mailBody, "message body", html);
          mailBody.flush();
          mailBody.close();
          html = mailBody.toString();
          MimeBodyPart htmlPart = new MimeBodyPart();
          htmlPart.setContent(html, ((Multipart)body).getBodyPart(0).getContentType());
          htmlPart.setHeader("Content-Type", ((Multipart)body).getBodyPart(0).getContentType());
          htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
          ((Multipart)body).removeBodyPart(0);
          ((Multipart)body).addBodyPart(htmlPart, 0);
          //replace related
          ((Multipart)content).removeBodyPart(1);
          MimeBodyPart relatedPart = new MimeBodyPart();
          relatedPart.setContent((Multipart) body);
          ((Multipart)content).addBodyPart(relatedPart, 1);
         
        }
        else
        {
          /*
           * -alternative (content)
           * \-text
           * |-html
           */
         
          //replace html
          String html = (String) ((Multipart)content).getBodyPart(1).getContent();
          StringWriter mailBody = new StringWriter();
          Velocity.evaluate(context, mailBody, "message body", html);
          mailBody.flush();
          mailBody.close();
          html = mailBody.toString();
          MimeBodyPart htmlPart = new MimeBodyPart();
          htmlPart.setContent(html, ((Multipart)content).getBodyPart(1).getContentType());
          htmlPart.setHeader("Content-Type", ((Multipart)content).getBodyPart(1).getContentType());
          htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
         
          ((Multipart)content).removeBodyPart(1);
          ((Multipart)content).addBodyPart(htmlPart);
        }
       
        if(alterTextCharset != null)
          setAlternativeText(alterText, alterTextCharset);
        else
          setAlternativeText(alterText, charset);
      }
      else if(content instanceof Multipart
          && ((Multipart)content).getContentType().startsWith("multipart/related"))
      {
        /*
         * -related (content)
         * \-html
         * |-attachment
         */
       
        //replace html
        String html = (String) ((Multipart)content).getBodyPart(0).getContent();
        StringWriter mailBody = new StringWriter();
        Velocity.evaluate(context, mailBody, "message body", html);
        mailBody.flush();
        mailBody.close();
        html = mailBody.toString();
        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent(html, ((Multipart)content).getBodyPart(0).getContentType());
        htmlPart.setHeader("Content-Type", ((Multipart)content).getBodyPart(0).getContentType());
        htmlPart.setHeader("Content-Transfer-Encoding", contentTransferEncoding);
        ((Multipart)content).removeBodyPart(0);
        ((Multipart)content).addBodyPart(htmlPart, 0);
      }
      else
      {
        /*
         * -html (content)
         */
       
        //replace html html
        String html = (String) content;
        StringWriter mailBody = new StringWriter();
        Velocity.evaluate(context, mailBody, "message body", html);
        mailBody.flush();
        mailBody.close();
        html = mailBody.toString();
        content = html;
      }
    }
   
    StringWriter subjectWriter = new StringWriter();
    Velocity.evaluate(context, subjectWriter, "message body", subject);
    subjectWriter.flush();
    subjectWriter.close();
    subject = subjectWriter.toString();
   
  }
 
 
}
TOP

Related Classes of com.qwertovsky.mailer.MessageContent

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.