blob: eb62b1ee809fe198fc711443410f9fbb57e9b651 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.apache.commons.mail;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.activation.URLDataSource;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimePart;
/**
* A multipart email.
*
* <p>This class is used to send multi-part internet email like
* messages with attachments.
*
* <p>To create a multi-part email, call the default constructor and
* then you can call setMsg() to set the message and call the
* different attach() methods.
*
* @since 1.0
* @version $Id$
*/
public class MultiPartEmail extends Email
{
/** Body portion of the email. */
private MimeMultipart container;
/** The message container. */
private BodyPart primaryBodyPart;
/** The MIME subtype. */
private String subType;
/** Indicates if the message has been initialized. */
private boolean initialized;
/** Indicates if attachments have been added to the message. */
private boolean boolHasAttachments;
/**
* Set the MIME subtype of the email.
*
* @param aSubType MIME subtype of the email
* @since 1.0
*/
public void setSubType(String aSubType)
{
this.subType = aSubType;
}
/**
* Get the MIME subtype of the email.
*
* @return MIME subtype of the email
* @since 1.0
*/
public String getSubType()
{
return subType;
}
/**
* Add a new part to the email.
*
* @param partContent The content.
* @param partContentType The content type.
* @return An Email.
* @throws EmailException see javax.mail.internet.MimeBodyPart
* for definitions
* @since 1.0
*/
public Email addPart(String partContent, String partContentType)
throws EmailException
{
BodyPart bodyPart = createBodyPart();
try
{
bodyPart.setContent(partContent, partContentType);
getContainer().addBodyPart(bodyPart);
}
catch (MessagingException me)
{
throw new EmailException(me);
}
return this;
}
/**
* Add a new part to the email.
*
* @param multipart The MimeMultipart.
* @return An Email.
* @throws EmailException see javax.mail.internet.MimeBodyPart
* for definitions
* @since 1.0
*/
public Email addPart(MimeMultipart multipart) throws EmailException
{
try
{
return addPart(multipart, getContainer().getCount());
}
catch (MessagingException me)
{
throw new EmailException(me);
}
}
/**
* Add a new part to the email.
*
* @param multipart The part to add.
* @param index The index to add at.
* @return The email.
* @throws EmailException An error occurred while adding the part.
* @since 1.0
*/
public Email addPart(MimeMultipart multipart, int index) throws EmailException
{
BodyPart bodyPart = createBodyPart();
try
{
bodyPart.setContent(multipart);
getContainer().addBodyPart(bodyPart, index);
}
catch (MessagingException me)
{
throw new EmailException(me);
}
return this;
}
/**
* Initialize the multipart email.
* @since 1.0
*/
protected void init()
{
if (initialized)
{
throw new IllegalStateException("Already initialized");
}
container = createMimeMultipart();
super.setContent(container);
initialized = true;
}
/**
* Set the message of the email.
*
* @param msg A String.
* @return An Email.
* @throws EmailException see javax.mail.internet.MimeBodyPart
* for definitions
* @since 1.0
*/
@Override
public Email setMsg(String msg) throws EmailException
{
// throw exception on null message
if (EmailUtils.isEmpty(msg))
{
throw new EmailException("Invalid message supplied");
}
try
{
BodyPart primary = getPrimaryBodyPart();
if ((primary instanceof MimePart) && EmailUtils.isNotEmpty(charset))
{
((MimePart) primary).setText(msg, charset);
}
else
{
primary.setText(msg);
}
}
catch (MessagingException me)
{
throw new EmailException(me);
}
return this;
}
/**
* Does the work of actually building the MimeMessage. Please note that
* a user rarely calls this method directly and only if he/she is
* interested in the sending the underlying MimeMessage without
* commons-email.
*
* @exception EmailException if there was an error.
* @since 1.0
*/
@Override
public void buildMimeMessage() throws EmailException
{
try
{
if (primaryBodyPart != null)
{
// before a multipart message can be sent, we must make sure that
// the content for the main body part was actually set. If not,
// an IOException will be thrown during super.send().
BodyPart body = this.getPrimaryBodyPart();
try
{
body.getContent();
}
catch (IOException e) // NOPMD
{
// do nothing here.
// content will be set to an empty string as a result.
// (Should this really be rethrown as an email exception?)
// throw new EmailException(e);
}
}
if (subType != null)
{
getContainer().setSubType(subType);
}
super.buildMimeMessage();
}
catch (MessagingException me)
{
throw new EmailException(me);
}
}
/**
* Attach a file.
*
* @param file A file attachment
* @return A MultiPartEmail.
* @throws EmailException see javax.mail.internet.MimeBodyPart
* for definitions
* @since 1.3
*/
public MultiPartEmail attach(File file)
throws EmailException
{
String fileName = file.getAbsolutePath();
try
{
if (!file.exists())
{
throw new IOException("\"" + fileName + "\" does not exist");
}
FileDataSource fds = new FileDataSource(file);
return attach(fds, file.getName(), null, EmailAttachment.ATTACHMENT);
}
catch (IOException e)
{
throw new EmailException("Cannot attach file \"" + fileName + "\"", e);
}
}
/**
* Attach an EmailAttachment.
*
* @param attachment An EmailAttachment.
* @return A MultiPartEmail.
* @throws EmailException see javax.mail.internet.MimeBodyPart
* for definitions
* @since 1.0
*/
public MultiPartEmail attach(EmailAttachment attachment)
throws EmailException
{
MultiPartEmail result = null;
if (attachment == null)
{
throw new EmailException("Invalid attachment supplied");
}
URL url = attachment.getURL();
if (url == null)
{
String fileName = null;
try
{
fileName = attachment.getPath();
File file = new File(fileName);
if (!file.exists())
{
throw new IOException("\"" + fileName + "\" does not exist");
}
result =
attach(
new FileDataSource(file),
attachment.getName(),
attachment.getDescription(),
attachment.getDisposition());
}
catch (IOException e)
{
throw new EmailException("Cannot attach file \"" + fileName + "\"", e);
}
}
else
{
result =
attach(
url,
attachment.getName(),
attachment.getDescription(),
attachment.getDisposition());
}
return result;
}
/**
* Attach a file located by its URL. The disposition of the file
* is set to mixed.
*
* @param url The URL of the file (may be any valid URL).
* @param name The name field for the attachment.
* @param description A description for the attachment.
* @return A MultiPartEmail.
* @throws EmailException see javax.mail.internet.MimeBodyPart
* for definitions
* @since 1.0
*/
public MultiPartEmail attach(URL url, String name, String description)
throws EmailException
{
return attach(url, name, description, EmailAttachment.ATTACHMENT);
}
/**
* Attach a file located by its URL.
*
* @param url The URL of the file (may be any valid URL).
* @param name The name field for the attachment.
* @param description A description for the attachment.
* @param disposition Either mixed or inline.
* @return A MultiPartEmail.
* @throws EmailException see javax.mail.internet.MimeBodyPart
* for definitions
* @since 1.0
*/
public MultiPartEmail attach(
URL url,
String name,
String description,
String disposition)
throws EmailException
{
// verify that the URL is valid
try
{
InputStream is = url.openStream();
is.close();
}
catch (IOException e)
{
throw new EmailException("Invalid URL set:" + url, e);
}
return attach(new URLDataSource(url), name, description, disposition);
}
/**
* Attach a file specified as a DataSource interface.
*
* @param ds A DataSource interface for the file.
* @param name The name field for the attachment.
* @param description A description for the attachment.
* @return A MultiPartEmail.
* @throws EmailException see javax.mail.internet.MimeBodyPart
* for definitions
* @since 1.0
*/
public MultiPartEmail attach(
DataSource ds,
String name,
String description)
throws EmailException
{
// verify that the DataSource is valid
try
{
final InputStream is = (ds != null) ? ds.getInputStream() : null;
if (is != null)
{
// close the input stream to prevent file locking on windows
is.close();
}
if (is == null)
{
throw new EmailException("Invalid Datasource");
}
}
catch (IOException e)
{
throw new EmailException("Invalid Datasource", e);
}
return attach(ds, name, description, EmailAttachment.ATTACHMENT);
}
/**
* Attach a file specified as a DataSource interface.
*
* @param ds A DataSource interface for the file.
* @param name The name field for the attachment.
* @param description A description for the attachment.
* @param disposition Either mixed or inline.
* @return A MultiPartEmail.
* @throws EmailException see javax.mail.internet.MimeBodyPart
* for definitions
* @since 1.0
*/
public MultiPartEmail attach(
DataSource ds,
String name,
String description,
String disposition)
throws EmailException
{
if (EmailUtils.isEmpty(name))
{
name = ds.getName();
}
BodyPart bodyPart = createBodyPart();
try
{
getContainer().addBodyPart(bodyPart);
bodyPart.setDisposition(disposition);
bodyPart.setFileName(name);
bodyPart.setDescription(description);
bodyPart.setDataHandler(new DataHandler(ds));
}
catch (MessagingException me)
{
throw new EmailException(me);
}
setBoolHasAttachments(true);
return this;
}
/**
* Gets first body part of the message.
*
* @return The primary body part.
* @throws MessagingException An error occurred while getting the primary body part.
* @since 1.0
*/
protected BodyPart getPrimaryBodyPart() throws MessagingException
{
if (!initialized)
{
init();
}
// Add the first body part to the message. The fist body part must be
if (this.primaryBodyPart == null)
{
primaryBodyPart = createBodyPart();
getContainer().addBodyPart(primaryBodyPart, 0);
}
return primaryBodyPart;
}
/**
* Gets the message container.
*
* @return The message container.
* @since 1.0
*/
protected MimeMultipart getContainer()
{
if (!initialized)
{
init();
}
return container;
}
/**
* Creates a body part object.
* Can be overridden if you don't want to create a BodyPart.
*
* @return the created body part
*/
protected BodyPart createBodyPart()
{
return new MimeBodyPart();
}
/**
* Creates a mime multipart object.
*
* @return the created mime part
*/
protected MimeMultipart createMimeMultipart()
{
return new MimeMultipart();
}
/**
* Checks whether there are attachments.
*
* @return true if there are attachments
* @since 1.0
*/
public boolean isBoolHasAttachments()
{
return boolHasAttachments;
}
/**
* Sets whether there are attachments.
*
* @param b the attachments flag
* @since 1.0
*/
public void setBoolHasAttachments(boolean b)
{
boolHasAttachments = b;
}
/**
* Checks if this object is initialized.
*
* @return true if initialized
*/
protected boolean isInitialized()
{
return initialized;
}
/**
* Sets the initialized status of this object.
*
* @param b the initialized status flag
*/
protected void setInitialized(boolean b)
{
initialized = b;
}
}