| /******************************************************************************* |
| * 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(); |
| } |
| } |
| } |