Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.exist.xquery.modules.mail.MessageFunctions Maven / Gradle / Ivy
package org.exist.xquery.modules.mail;
import org.exist.dom.memtree.MemTreeBuilder;
import org.exist.dom.memtree.ElementImpl;
import org.exist.dom.memtree.DocumentBuilderReceiver;
import org.exist.dom.memtree.DocumentImpl;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.regex.Pattern;
import javax.activation.MimeType;
import javax.activation.MimeTypeParameterList;
import javax.activation.MimeTypeParseException;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.xml.transform.stream.StreamSource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.exist.dom.QName;
import org.exist.xquery.BasicFunction;
import org.exist.xquery.Cardinality;
import org.exist.xquery.FunctionSignature;
import org.exist.xquery.XPathException;
import org.exist.xquery.XQueryContext;
import org.exist.xquery.modules.ModuleUtils;
import org.exist.xquery.value.*;
import org.xml.sax.SAXException;
/**
* Modified by alisterpillow on 19/08/2014.
* Get a mail message
*
* @author Andrzej Taramina
* @serial 2009-03-12
* @version 1.3
*
* @see org.exist.xquery.BasicFunction#BasicFunction(org.exist.xquery.XQueryContext, org.exist.xquery.FunctionSignature)
*/
public class MessageFunctions extends BasicFunction {
protected static final Logger logger = LogManager.getLogger(MessageListFunctions.class);
private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
private static final Pattern CONTENT_TYPE_RE = Pattern.compile(";\\s*boundary(.*)$"); // Remove unnecessary boundary= from content-type
public final static FunctionSignature signatures[] = {
new FunctionSignature(
new QName("get-messages", MailModule.NAMESPACE_URI, MailModule.PREFIX),
"Returns a sequence of emails as XML. If there are no messages-numbers in the list, an empty sequence will be returned. Please see get_messages_example.xql.",
new SequenceType[]
{
new FunctionParameterSequenceType("message-list-handle", Type.INTEGER, Cardinality.EXACTLY_ONE, "The message list handle retrieved from mail:get-message-list() or mail:search-message-list()"),
new FunctionParameterSequenceType("message-numbers", Type.INTEGER, Cardinality.ZERO_OR_MORE, "The messages to retrieve using the numbers from the message-list '//mail:message/@number' ")
},
new FunctionReturnSequenceType(Type.ELEMENT, Cardinality.ZERO_OR_ONE, "the chosen messages as XML mail:messages/mail:message")
)
};
public MessageFunctions(XQueryContext context, FunctionSignature signature) {
super(context, signature);
}
/**
* evaluate the call to the xquery get-message function,
* it is really the main entry point of this class
*
* @param args arguments from the get-message-list() function call
* @param contextSequence the Context Sequence to operate on (not used here internally!)
* @return A sequence representing the result of the get-message-list() function call
* @see org.exist.xquery.BasicFunction#eval(org.exist.xquery.value.Sequence[], org.exist.xquery.value.Sequence)
*/
public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException {
if (isCalledAs("get-messages")) {
return getMessages(args, contextSequence);
}
throw (new XPathException(this, "Invalid function name"));
}
private Sequence getMessages(Sequence[] args, Sequence contextSequence) throws XPathException
{
Sequence ret = Sequence.EMPTY_SEQUENCE;
// was a folder handle specified?
if (args[0].isEmpty()) {
throw (new XPathException(this, "Mail folder handle not specified"));
}
// get the Folder
long folderHandle = ((IntegerValue)args[0].itemAt(0)).getLong();
Folder folder= MailModule.retrieveFolder( context, folderHandle );
if( folder == null ) {
throw( new XPathException(this, "Invalid Folder handle specified" ) );
}
if (args[1].isEmpty()) { // expecting a sequence of message numbers
return ret; // no messages requested
}
MemTreeBuilder builder = context.getDocumentBuilder();
builder.startDocument();
builder.startElement(new QName("messages", MailModule.NAMESPACE_URI, MailModule.PREFIX), null);
try {
int counter = args[1].getItemCount();
for (int i = 0; i < counter; i++) {
Message message = null;
int msgNum = ((IntegerValue)args[1].itemAt(i)).getInt();
try {
message = folder.getMessage(msgNum); // get the requested message number
} catch (IndexOutOfBoundsException iex) {
logger.info("There is no message number " + msgNum);
continue;
}
builder.startElement(new QName("message", MailModule.NAMESPACE_URI, MailModule.PREFIX), null);
builder.addAttribute(new QName("number", null, null), String.valueOf(message.getMessageNumber()));
String contentType = message.getContentType();
mimeParamsToAttributes(builder, contentType);
// Subject
builder.startElement( new QName( "subject", MailModule.NAMESPACE_URI, MailModule.PREFIX ), null );
builder.characters( message.getSubject() );
builder.endElement();
// Sent Date
if (message.getSentDate() != null) {
builder.startElement(new QName("sent", MailModule.NAMESPACE_URI, MailModule.PREFIX), null);
builder.characters(formatDate(message.getSentDate()));
builder.endElement();
}
// Received Date
if (message.getReceivedDate() != null) {
builder.startElement(new QName("received", MailModule.NAMESPACE_URI, MailModule.PREFIX), null);
builder.characters(formatDate(message.getReceivedDate()));
builder.endElement();
}
// From
if (message.getFrom() != null) {
addAddress(builder,"from", null, message.getFrom()[0]);
}
// Recipients
builder.startElement(new QName("recipients", MailModule.NAMESPACE_URI, MailModule.PREFIX), null);
// To Recipients
Address[] toAddresses = message.getRecipients(Message.RecipientType.TO);
if (toAddresses != null) {
for (Address to : toAddresses) {
addAddress(builder, "recipient","to",to);
}
}
// cc Recipients
Address[] ccAddresses = message.getRecipients(Message.RecipientType.CC);
if (ccAddresses != null) {
for (Address ccAddress : ccAddresses) {
addAddress(builder,"recipient", "cc", ccAddress);
}
}
// bcc Recipients
Address[] bccAddresses = message.getRecipients(Message.RecipientType.BCC);
if (bccAddresses != null) {
for (Address bccAddress : bccAddresses) {
addAddress(builder,"recipient", "bcc", bccAddress);
}
}
builder.endElement(); // recipients
// Handle the content
Object content = message.getContent();
if (content instanceof Multipart) {
handleMultipart((Multipart)content, builder);
} else {
handlePart(message, builder);
}
// Flags
Flags flags = message.getFlags();
Flags.Flag[] systemFlags = flags.getSystemFlags();
String[] userFlags = flags.getUserFlags();
if (systemFlags.length > 0 || userFlags.length > 0) {
builder.startElement(new QName("flags", MailModule.NAMESPACE_URI, MailModule.PREFIX), null);
for (Flags.Flag systemFlag : systemFlags) {
if (systemFlag == Flags.Flag.ANSWERED) {
addFlag(builder,"answered");
} else if (systemFlag == Flags.Flag.DELETED) {
addFlag(builder,"deleted");
} else if (systemFlag == Flags.Flag.DRAFT) {
addFlag(builder, "draft");
} else if (systemFlag == Flags.Flag.FLAGGED) {
addFlag(builder,"flagged");
} else if (systemFlag == Flags.Flag.RECENT) {
addFlag(builder,"recent");
} else if (systemFlag == Flags.Flag.SEEN) {
addFlag(builder,"seen");
}
}
for (String userFlag : userFlags) {
builder.startElement(new QName("flag", MailModule.NAMESPACE_URI, MailModule.PREFIX), null);
builder.addAttribute(new QName("type", null, null), "user");
builder.addAttribute(new QName("value", null, null), userFlag);
builder.endElement();
}
builder.endElement();
}
builder.endElement();
}
} catch (MessagingException me) {
throw (new XPathException(this, "Failed to retrieve messages from list", me));
} catch (IOException | SAXException e) {
e.printStackTrace();
}
builder.endElement();
builder.endDocument();
ret = (NodeValue) builder.getDocument().getDocumentElement();
return (ret);
}
private void addFlag(MemTreeBuilder builder, String flag) {
builder.startElement(new QName("flag", MailModule.NAMESPACE_URI, MailModule.PREFIX), null);
builder.addAttribute(new QName("type", null, null), flag);
builder.endElement();
}
private void addAddress(MemTreeBuilder builder, String element, String attrVal, Address addr ) {
builder.startElement(new QName(element, MailModule.NAMESPACE_URI, MailModule.PREFIX), null);
if (attrVal != null) builder.addAttribute(new QName("type", null, null), attrVal);
InternetAddress ia = (InternetAddress)addr;
if (ia.getPersonal() != null) {
builder.addAttribute(new QName("personal", null, null),ia.getPersonal());
builder.characters(ia.getAddress());
} else {
builder.characters(ia.getAddress());
}
builder.endElement();
}
private String formatDate(Date date) {
String formatted = "";
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
String temp = sdf.format(date);
formatted = temp.substring(0, temp.length() - 2) + ":" + temp.substring(temp.length() - 2);
return (formatted);
}
private void handleMultipart(Multipart multipart, MemTreeBuilder builder)
throws MessagingException, IOException, XPathException, SAXException {
for (int i=0, n=multipart.getCount(); i
Additionally, the namespace binding is dropped - so this throws an error when the content is parsed.
*/
try (InputStream inputStream = part.getInputStream()) {
DocumentImpl html = ModuleUtils.htmlToXHtml(context, new StreamSource(inputStream), null, null);
ElementImpl rootElem = (ElementImpl) html.getDocumentElement();
html.copyTo(rootElem,receiver);
builder.endElement();
}
} else if (disposition.equalsIgnoreCase(Part.ATTACHMENT)) {
builder.startElement(new QName("attachment", MailModule.NAMESPACE_URI, MailModule.PREFIX), null);
builder.addAttribute(new QName("filename", null, null), part.getFileName());
mimeParamsToAttributes(builder, part.getContentType());
handleBinaryContent(part, builder);
builder.endElement();
} else if (disposition.equalsIgnoreCase(Part.INLINE)) {
builder.startElement(new QName("inline", MailModule.NAMESPACE_URI, MailModule.PREFIX), null);
MimeBodyPart mbp = (MimeBodyPart)part;
builder.addAttribute(new QName("filename", null, null), mbp.getFileName());
// fix content id so that it matches the cid: format within the html
if (mbp.getContentID()!= null) {
builder.addAttribute(new QName("content-id", null, null), "cid:" + mbp.getContentID().replaceAll("^<|>$", ""));
}
mimeParamsToAttributes(builder, part.getContentType());
handleBinaryContent(part, builder);
builder.endElement();
} else { // Should never happen
builder.startElement(new QName("other", MailModule.NAMESPACE_URI, MailModule.PREFIX), null);
mimeParamsToAttributes(builder, part.getContentType());
builder.addAttribute(new QName("disposition",null,null), part.getDisposition());
builder.characters(part.getContent().toString());
builder.endElement();
}
}
private void handleBinaryContent(Part part, MemTreeBuilder builder) throws IOException, MessagingException, XPathException {
builder.addAttribute(new QName("type", null, null), "binary");
builder.addAttribute( new QName( "encoding", null, null ), "Base64Encoded" );
BinaryValue binary = null;
try {
binary = BinaryValueFromInputStream.getInstance(context, new Base64BinaryValueType(), part.getInputStream());
builder.characters(binary.getStringValue());
} finally {
// free resources
if (binary != null) {
binary.destroy(context, null);
}
}
}
}