blob: a49806e6c182f6700f3811938e70a17cda5cbcd4 [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.ofbiz.service.mail;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.sql.Timestamp;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import org.ofbiz.base.conversion.AbstractConverter;
import org.ofbiz.base.conversion.ConversionException;
import org.ofbiz.base.conversion.Converters;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralRuntimeException;
import org.ofbiz.base.util.UtilDateTime;
@SuppressWarnings("serial")
public class MimeMessageWrapper implements java.io.Serializable {
public static final String module = MimeMessageWrapper.class.getName();
protected transient MimeMessage message = null;
protected transient Session session = null;
protected Properties mailProperties = null;
protected String contentType = null;
protected byte[] serializedBytes = null;
protected int parts = 0;
public MimeMessageWrapper(Session session, MimeMessage message) {
this(session);
this.setMessage(message);
}
public MimeMessageWrapper(Session session) {
this.setSession(session);
}
public void setSession(Session session) {
this.session = session;
this.mailProperties = session.getProperties();
}
public synchronized Session getSession() {
if (session == null) {
session = Session.getInstance(mailProperties, null);
}
return session;
}
public void setMessage(MimeMessage message) {
if (message != null) {
// serialize the message
this.message = message;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
message.writeTo(baos);
baos.flush();
serializedBytes = baos.toByteArray();
this.contentType = message.getContentType();
// see if this is a multi-part message
Object content = message.getContent();
if (content instanceof Multipart) {
Multipart mp = (Multipart) content;
this.parts = mp.getCount();
} else {
this.parts = 0;
}
} catch (MessagingException e) {
Debug.logError(e, module);
} catch (IOException e) {
Debug.logError(e, module);
} finally {
try {
baos.close();
} catch (IOException e) {
Debug.logError(e, module);
}
}
}
}
public synchronized MimeMessage getMessage() {
if (message == null) {
// deserialize the message
if (serializedBytes != null) {
ByteArrayInputStream bais = new ByteArrayInputStream(serializedBytes);
try {
message = new MimeMessage(this.getSession(), bais);
} catch (MessagingException e) {
Debug.logError(e, module);
throw new GeneralRuntimeException(e.getMessage(), e);
}
}
}
return message;
}
public String getFirstHeader(String header) {
String[] headers = getHeader(header);
if (headers != null && headers.length > 0) {
return headers[0];
} else {
return null;
}
}
public String[] getHeader(String header) {
MimeMessage message = getMessage();
try {
return message.getHeader(header);
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
}
public Address[] getFrom() {
MimeMessage message = getMessage();
try {
return message.getFrom();
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
}
public Address[] getTo() {
MimeMessage message = getMessage();
try {
return message.getRecipients(MimeMessage.RecipientType.TO);
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
}
public Address[] getCc() {
MimeMessage message = getMessage();
try {
return message.getRecipients(MimeMessage.RecipientType.CC);
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
}
public Address[] getBcc() {
MimeMessage message = getMessage();
try {
return message.getRecipients(MimeMessage.RecipientType.BCC);
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
}
public String getSubject() {
MimeMessage message = getMessage();
try {
return message.getSubject();
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
}
public String getMessageId() {
MimeMessage message = getMessage();
try {
return message.getMessageID();
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
}
public Timestamp getSentDate() {
MimeMessage message = getMessage();
try {
return UtilDateTime.toTimestamp(message.getSentDate());
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
}
public Timestamp getReceivedDate() {
MimeMessage message = getMessage();
try {
return UtilDateTime.toTimestamp(message.getReceivedDate());
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
}
public String getContentType() {
return contentType;
}
public int getMainPartCount() {
return this.parts;
}
public int getSubPartCount(int index) {
BodyPart part = getPart(Integer.toString(index));
try {
Object content = part.getContent();
if (content instanceof Multipart) {
return ((Multipart) content).getCount();
} else {
return 0;
}
} catch (Exception e) {
Debug.logError(e, module);
return -1;
}
}
public List<String> getAttachmentIndexes() {
List<String> attachments = new LinkedList<String>();
if (getMainPartCount() == 0) { // single part message (no attachments)
return attachments;
} else {
for (int i = 0; i < getMainPartCount(); i++) {
int subPartCount = getSubPartCount(i);
String idx = Integer.toString(i);
if (subPartCount > 0) {
for (int si = 0; si < subPartCount; si++) {
String sidx = idx + "." + Integer.toString(si);
if (getPartDisposition(sidx) != null && (getPartDisposition(sidx).equalsIgnoreCase(Part.ATTACHMENT) ||
getPartDisposition(sidx).equalsIgnoreCase(Part.INLINE))) {
attachments.add(sidx);
}
}
} else {
if (getPartDisposition(idx) != null && (getPartDisposition(idx).equalsIgnoreCase(Part.ATTACHMENT) ||
getPartDisposition(idx).equalsIgnoreCase(Part.INLINE))) {
attachments.add(idx);
}
}
}
return attachments;
}
}
public String getMessageBody() {
MimeMessage message = getMessage();
if (getMainPartCount() == 0) { // single part message
try {
Object content = message.getContent();
return getContentText(content);
} catch (Exception e) {
Debug.logError(e, module);
return null;
}
} else { // multi-part message
StringBuffer body = new StringBuffer();
for (int i = 0; i < getMainPartCount(); i++) {
int subPartCount = getSubPartCount(i);
String idx = Integer.toString(i);
if (subPartCount > 0) {
for (int si = 0; si < subPartCount; si++) {
String sidx = idx + "." + Integer.toString(si);
if (getPartContentType(sidx) != null && getPartContentType(sidx).toLowerCase().startsWith("text")) {
if (getPartDisposition(sidx) == null || getPartDisposition(sidx).equals(Part.INLINE)) {
body.append(getPartText(sidx)).append("\n");
}
}
}
} else {
if (getPartContentType(idx) != null && getPartContentType(idx).toLowerCase().startsWith("text")) {
// make sure the part isn't an attachment
if (getPartDisposition(idx) == null || getPartDisposition(idx).equals(Part.INLINE)) {
body.append(getPartText(idx)).append("\n");
}
}
}
}
return body.toString();
}
}
public String getMessageBodyContentType() {
String contentType = getContentType();
if (contentType != null && contentType.toLowerCase().startsWith("text")) {
return contentType;
} else {
for (int i = 0; i < getMainPartCount(); i++) {
int subPartCount = getSubPartCount(i);
String idx = Integer.toString(i);
if (subPartCount > 0) {
for (int si = 0; si < subPartCount; si++) {
String sidx = idx + "." + Integer.toString(si);
if (getPartContentType(sidx) != null && getPartContentType(sidx).toLowerCase().startsWith("text")) {
if (getPartDisposition(sidx) == null || getPartDisposition(sidx).equals(Part.INLINE)) {
return getPartContentType(sidx);
}
}
}
} else {
if (getPartContentType(idx) != null && getPartContentType(idx).toLowerCase().startsWith("text")) {
// make sure the part isn't an attachment
if (getPartDisposition(idx) == null || getPartDisposition(idx).equals(Part.INLINE)) {
return getPartContentType(idx);
}
}
}
}
}
return "text/html";
}
public String getMessageRawText() {
MimeMessage message = getMessage();
try {
return getTextFromStream(message.getInputStream());
} catch (Exception e) {
Debug.logError(e, module);
return null;
}
}
public String getPartDescription(String index) {
BodyPart part = getPart(index);
if (part != null) {
try {
return part.getDescription();
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
} else {
return null;
}
}
public String getPartContentType(String index) {
BodyPart part = getPart(index);
if (part != null) {
try {
return part.getContentType();
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
} else {
return null;
}
}
public String getPartDisposition(String index) {
BodyPart part = getPart(index);
if (part != null) {
try {
return part.getDisposition();
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
} else {
return null;
}
}
public String getPartFilename(String index) {
BodyPart part = getPart(index);
if (part != null) {
try {
return part.getFileName();
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
}
} else {
return null;
}
}
public ByteBuffer getPartByteBuffer(String index) {
BodyPart part = getPart(index);
if (part != null) {
try {
InputStream stream = part.getInputStream();
return getByteBufferFromStream(stream);
} catch (Exception e) {
Debug.logError(e, module);
return null;
}
} else {
return null;
}
}
public String getPartText(String index) {
BodyPart part = getPart(index);
if (part != null) {
try {
return getContentText(part.getContent());
} catch (Exception e) {
Debug.logError(e, module);
return null;
}
} else {
return null;
}
}
public String getPartRawText(String index) {
BodyPart part = getPart(index);
if (part != null) {
try {
return getTextFromStream(part.getInputStream());
} catch (Exception e) {
Debug.logError(e, module);
return null;
}
} else {
return null;
}
}
public BodyPart getPart(String indexStr) {
int mainIndex, subIndex;
try {
if (indexStr.indexOf(".") == -1) {
mainIndex = Integer.parseInt(indexStr);
subIndex = -1;
} else {
String[] indexSplit = indexStr.split("\\.");
mainIndex = Integer.parseInt(indexSplit[0]);
subIndex = Integer.parseInt(indexSplit[1]);
}
} catch (NumberFormatException e) {
Debug.logError(e, "Illegal index string format. Should be part 'dot' subpart: " + indexStr, module);
return null;
} catch (ArrayIndexOutOfBoundsException e) {
Debug.logError(e, "Illegal index string format. Should be part 'dot' subpart: " + indexStr, module);
return null;
}
if (getMainPartCount() > 0 && getMainPartCount() > mainIndex) {
MimeMessage message = this.getMessage();
try {
Multipart mp = (Multipart) message.getContent();
if (subIndex == -1) {
return mp.getBodyPart(mainIndex);
} else {
BodyPart part = mp.getBodyPart(mainIndex);
int subPartCount = getSubPartCount(mainIndex);
if (subPartCount > subIndex) {
Multipart sp = (Multipart) part.getContent();
return sp.getBodyPart(subIndex);
} else {
Debug.logWarning("Requested a subpart [" + subIndex + "] which deos not exist; only [" + getSubPartCount(mainIndex) + "] parts", module);
// there is no sub part to find
return part;
}
}
} catch (MessagingException e) {
Debug.logError(e, module);
return null;
} catch (IOException e) {
Debug.logError(e, module);
return null;
}
} else {
Debug.logWarning("Requested a part [" + mainIndex + "] which deos not exist; only [" + getMainPartCount() + "] parts", module);
return null;
}
}
protected String getContentText(Object content) {
if (content == null) return null;
if (content instanceof String) {
return (String) content;
} else if (content instanceof InputStream) {
return getTextFromStream((InputStream) content);
} else if (content instanceof Message) {
try {
return getTextFromStream(((Message) content).getInputStream());
} catch (Exception e) {
Debug.logError(e, module);
return null;
}
} else {
Debug.logWarning("Content was not a string or a stream; no known handler -- " + content.toString(), module);
return null;
}
}
protected String getTextFromStream(InputStream stream) {
StringBuilder builder = new StringBuilder();
byte[] buffer = new byte[4096];
try {
for (int n; (n = stream.read(buffer)) != -1;) {
builder.append(new String(buffer, 0, n));
}
} catch (IOException e) {
Debug.logError(e, module);
return null;
}
return builder.toString();
}
protected ByteBuffer getByteBufferFromStream(InputStream stream) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
try {
for (int n; (n = stream.read(buffer)) != -1;) {
baos.write(buffer, 0, n);
}
} catch (IOException e) {
Debug.logError(e, module);
return null;
}
return ByteBuffer.wrap(baos.toByteArray());
}
static {
Converters.registerConverter(new MimeMessageToString<String>());
}
/**
* Convert MimeMessageWrapper to String. This is used when sending emails.
*
*/
private static class MimeMessageToString<E> extends AbstractConverter<MimeMessageWrapper, String> {
public MimeMessageToString() {
super(MimeMessageWrapper.class, String.class);
}
public String convert(MimeMessageWrapper obj) throws ConversionException {
return obj.toString();
}
}
}