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.
io.cloudslang.content.mail.services.GetMailMessage Maven / Gradle / Ivy
package io.cloudslang.content.mail.services;
import com.sun.mail.util.ASCIIUtility;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.cms.RecipientId;
import org.bouncycastle.cms.RecipientInformation;
import org.bouncycastle.cms.RecipientInformationStore;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.mail.smime.SMIMEEnveloped;
import org.bouncycastle.mail.smime.SMIMEUtil;
import io.cloudslang.content.mail.entities.GetMailMessageInputs;
import io.cloudslang.content.mail.entities.SimpleAuthenticator;
import io.cloudslang.content.mail.entities.StringOutputStream;
import io.cloudslang.content.mail.sslconfig.EasyX509TrustManager;
import io.cloudslang.content.mail.sslconfig.SSLUtils;
import javax.mail.*;
import javax.mail.NoSuchProviderException;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.URL;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.*;
/**
* Created by giloan on 11/3/2014.
*/
public class GetMailMessage {
public static final String RETURN_RESULT = "returnResult";
public static final String SUBJECT = "Subject";
public static final String BODY_RESULT = "Body";
public static final String PLAIN_TEXT_BODY_RESULT = "plainTextBody";
public static final String ATTACHED_FILE_NAMES_RESULT = "AttachedFileNames";
public static final String RETURN_CODE = "returnCode";
public static final String EXCEPTION = "exception";
public static final String SUCCESS = "success";
public static final String FAILURE = "failure";
public static final String SUCCESS_RETURN_CODE = "0";
public static final String FAILURE_RETURN_CODE = "-1";
public static final String FILE = "file:";
public static final String HTTP = "http";
public static final String DEFAULT_PASSWORD_FOR_STORE = "changeit";
public static final String POP3 = "pop3";
public static final String IMAP = "imap";
public static final String IMAP_4 = "imap4";
public static final String IMAP_PORT = "143";
public static final String POP3_PORT = "110";
public static final String PLEASE_SPECIFY_THE_PORT_FOR_THE_INDICATED_PROTOCOL = "Please specify the port for the indicated protocol.";
public static final String PLEASE_SPECIFY_THE_PORT_THE_PROTOCOL_OR_BOTH = "Please specify the port, the protocol, or both.";
public static final String PLEASE_SPECIFY_THE_PROTOCOL_FOR_THE_INDICATED_PORT = "Please specify the protocol for the indicated port.";
public static final String TEXT_PLAIN = "text/plain";
public static final String TEXT_HTML = "text/html";
private static final String MULTIPART_MIXED = "multipart/mixed";
private static final String MULTIPART_RELATED = "multipart/related";
public static final String CONTENT_TYPE = "Content-Type";
public static final String SSL = "SSL";
public static final String STR_FALSE = "false";
public static final String STR_TRUE = "true";
public static final String MESSAGES_ARE_NUMBERED_STARTING_AT_1 = "Messages are numbered starting at 1 through the total number of messages in the folder!";
public static final String STR_COMMA = ",";
public static final String THE_SPECIFIED_FOLDER_DOES_NOT_EXIST_ON_THE_REMOTE_SERVER = "The specified folder does not exist on the remote server.";
public static final String UNRECOGNIZED_SSL_MESSAGE = "Unrecognized SSL message";
public static final String UNRECOGNIZED_SSL_MESSAGE_PLAINTEXT_CONNECTION = "Unrecognized SSL message, plaintext connection?";
public static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
private static final String HOST_NOT_SPECIFIED = "The required host input is not specified!";
private static final String MESSAGE_NUMBER_NOT_SPECIFIED = "The required messageNumber input is not specified!";
private static final String USERNAME_NOT_SPECIFIED = "The required username input is not specified!";
private static final String FOLDER_NOT_SPECIFIED = "The required folder input is not specified!";
public static final String PKCS_KEYSTORE_TYPE = "PKCS12";
public static final String BOUNCY_CASTLE_PROVIDER = "BC";
public static final String ENCRYPTED_CONTENT_TYPE = "application/pkcs7-mime; name=\"smime.p7m\"; smime-type=enveloped-data";
public static final String SECURE_SUFFIX_FOR_POP3_AND_IMAP = "s";
//Operation inputs
private String host;
private String port;
private String protocol;
private String username;
private String password;
private String folder;
private boolean trustAllRoots;
/**
* The relative position of the message in the folder. Numbering starts from 1.
*/
private int messageNumber;
private boolean subjectOnly = true;
private boolean enableSSL;
private boolean enableTLS;
private String keystore;
private String keystorePassword;
private String trustKeystoreFile;
private String trustPassword;
private String characterSet;
private String decryptionKeystore;
private String decryptionKeyAlias;
private String decryptionKeystorePass;
private boolean deleteUponRetrieval;
private boolean decryptMessage;
private int timeout = -1;
private boolean verifyCertificate = false;
private RecipientId recId = null;
private KeyStore ks = null;
public Map execute(GetMailMessageInputs getMailMessageInputs) throws Exception {
Map result = new HashMap<>();
try {
processInputs(getMailMessageInputs);
Message message = getMessage();
if (decryptMessage) {
addDecryptionSettings();
}
//delete message
if (deleteUponRetrieval) {
message.setFlag(Flags.Flag.DELETED, true);
}
if (subjectOnly) {
String subject;
if ((characterSet != null) && (characterSet.trim().length() > 0)) { //need to force the decode charset
subject = message.getHeader(SUBJECT)[0];
subject = changeHeaderCharset(subject, characterSet);
subject = MimeUtility.decodeText(subject);
} else {
subject = message.getSubject();
}
if (subject == null) {
subject = "";
}
result.put(RETURN_RESULT, MimeUtility.decodeText(subject));
} else {
try {
// Get subject and attachedFileNames
if ((characterSet != null) && (characterSet.trim().length() > 0)) { //need to force the decode charset
String subject = message.getHeader(SUBJECT)[0];
subject = changeHeaderCharset(subject, characterSet);
result.put(SUBJECT, MimeUtility.decodeText(subject));
String attachedFileNames = changeHeaderCharset(getAttachedFileNames(message), characterSet);
result.put(ATTACHED_FILE_NAMES_RESULT, decodeAttachedFileNames(attachedFileNames));
} else { //let everything as the sender intended it to be :)
String subject = message.getSubject();
if (subject == null)
subject = "";
result.put(SUBJECT, MimeUtility.decodeText(subject));
result.put(ATTACHED_FILE_NAMES_RESULT, decodeAttachedFileNames((getAttachedFileNames(message))));
}
// Get the message body
Map messageByTypes = getMessageByContentTypes(message, characterSet);
String lastMessageBody = "";
if(!messageByTypes.isEmpty()) {
lastMessageBody = new LinkedList<>(messageByTypes.values()).getLast();
}
if(lastMessageBody == null) {
lastMessageBody = "";
}
result.put(BODY_RESULT, MimeUtility.decodeText(lastMessageBody));
String plainTextBody = messageByTypes.containsKey(TEXT_PLAIN) ? messageByTypes.get(TEXT_PLAIN) : "";
result.put(PLAIN_TEXT_BODY_RESULT, MimeUtility.decodeText(plainTextBody));
StringOutputStream stream = new StringOutputStream();
message.writeTo(stream);
result.put(RETURN_RESULT, stream.toString().replaceAll("" + (char) 0, ""));
} catch (UnsupportedEncodingException except) {
throw new UnsupportedEncodingException("The given encoding (" + characterSet + ") is invalid or not supported.");
}
}
message.getFolder().close(true);
result.put(RETURN_CODE, SUCCESS_RETURN_CODE);
} catch (Exception e) {
if (e.toString().contains(UNRECOGNIZED_SSL_MESSAGE)) {
throw new Exception(UNRECOGNIZED_SSL_MESSAGE_PLAINTEXT_CONNECTION);
} else {
throw e;
}
}
return result;
}
protected Message getMessage() throws Exception {
Store store = createMessageStore();
Folder f = store.getFolder(folder);
if (!f.exists()) {
throw new Exception(THE_SPECIFIED_FOLDER_DOES_NOT_EXIST_ON_THE_REMOTE_SERVER);
}
f.open(getFolderOpenMode());
if (messageNumber > f.getMessageCount())
throw new IndexOutOfBoundsException("message value was: " + messageNumber + " there are only " + f.getMessageCount() + " messages in folder");
return f.getMessage(messageNumber);
}
protected Store createMessageStore() throws Exception {
Properties props = new Properties();
if(timeout > 0) {
props.put("mail." + protocol + ".timeout", timeout);
}
Authenticator auth = new SimpleAuthenticator(username, password);
Store store;
if (enableTLS || enableSSL) addSSLSettings(trustAllRoots, keystore, keystorePassword, trustKeystoreFile, trustPassword);
if (enableTLS) {
store = tryTLSOtherwiseTrySSL(props, auth);
} else if (enableSSL) {
store = connectUsingSSL(props, auth);
} else {
store = configureStoreWithoutSSL(props, auth);
store.connect();
}
return store;
}
private Store tryTLSOtherwiseTrySSL(Properties props, Authenticator auth) throws MessagingException {
Store store = configureStoreWithTLS(props, auth);
try {
store.connect(host, username, password);
} catch (Exception e) {
if (enableSSL) {
clearTLSProperties(props);
store = connectUsingSSL(props, auth);
} else {
throw e;
}
}
return store;
}
private Store connectUsingSSL(Properties props, Authenticator auth) throws MessagingException {
Store store = configureStoreWithSSL(props, auth);
store.connect();
return store;
}
private void clearTLSProperties(Properties props) {
props.remove("mail." + protocol + ".ssl.enable");
props.remove("mail." + protocol + ".starttls.enable");
props.remove("mail." + protocol + ".starttls.required");
}
protected Store configureStoreWithSSL(Properties props, Authenticator auth) throws NoSuchProviderException {
props.setProperty("mail." + protocol + ".socketFactory.class", SSL_FACTORY);
props.setProperty("mail." + protocol + ".socketFactory.fallback", STR_FALSE);
props.setProperty("mail." + protocol + ".port", port);
props.setProperty("mail." + protocol + ".socketFactory.port", port);
URLName url = new URLName(protocol, host, Integer.parseInt(port), "", username, password);
Session session = Session.getInstance(props, auth);
return session.getStore(url);
}
protected Store configureStoreWithTLS(Properties props, Authenticator auth) throws NoSuchProviderException {
props.setProperty("mail." + protocol + ".ssl.enable", STR_FALSE);
props.setProperty("mail." + protocol + ".starttls.enable", STR_TRUE);
props.setProperty("mail." + protocol + ".starttls.required", STR_TRUE);
Session session = Session.getInstance(props, auth);
return session.getStore(protocol + SECURE_SUFFIX_FOR_POP3_AND_IMAP);
}
protected Store configureStoreWithoutSSL(Properties props, Authenticator auth) throws NoSuchProviderException {
props.put("mail." + protocol + ".host", host);
props.put("mail." + protocol + ".port", port);
Session s = Session.getInstance(props, auth);
return s.getStore(protocol);
}
protected void addSSLSettings(boolean trustAllRoots, String keystore,
String keystorePassword, String trustKeystore, String trustPassword) throws Exception {
boolean useClientCert = false;
boolean useTrustCert = false;
String separator = getSystemFileSeparator();
String javaKeystore = getSystemJavaHome() + separator + "lib" + separator + "security" + separator + "cacerts";
if (keystore.length() == 0 && !trustAllRoots) {
boolean storeExists = new File(javaKeystore).exists();
keystore = (storeExists) ? FILE + javaKeystore : null;
if (null != keystorePassword) {
if (keystorePassword.equals("")) {
keystorePassword = DEFAULT_PASSWORD_FOR_STORE;
}
}
useClientCert = storeExists;
} else {
if (!trustAllRoots) {
if (!keystore.startsWith(HTTP))
keystore = FILE + keystore;
useClientCert = true;
}
}
if (trustKeystore.length() == 0 && !trustAllRoots) {
boolean storeExists = new File(javaKeystore).exists();
trustKeystore = (storeExists) ? FILE + javaKeystore : null;
trustPassword = (storeExists) ? ((trustPassword.equals("")) ? DEFAULT_PASSWORD_FOR_STORE : trustPassword) : null;
useTrustCert = storeExists;
} else {
if (!trustAllRoots) {
if (!trustKeystore.startsWith(HTTP))
trustKeystore = FILE + trustKeystore;
useTrustCert = true;
}
}
SSLContext context = SSLContext.getInstance(SSL);
TrustManager[] trustManagers = null;
KeyManager[] keyManagers = null;
if (trustAllRoots) {
trustManagers = new TrustManager[]{new EasyX509TrustManager()};
}
if (useTrustCert) {
KeyStore trustKeyStore = SSLUtils.createKeyStore(new URL(trustKeystore), trustPassword);
trustManagers = SSLUtils.createAuthTrustManagers(trustKeyStore);
}
if (useClientCert) {
KeyStore clientKeyStore = SSLUtils.createKeyStore(new URL(keystore), keystorePassword);
keyManagers = SSLUtils.createKeyManagers(clientKeyStore, keystorePassword);
}
context.init(keyManagers, trustManagers, new SecureRandom());
SSLContext.setDefault(context);
}
private void addDecryptionSettings() throws Exception {
char[] smimePw = new String(decryptionKeystorePass).toCharArray();
Security.addProvider(new BouncyCastleProvider());
ks = KeyStore.getInstance(PKCS_KEYSTORE_TYPE, BOUNCY_CASTLE_PROVIDER);
InputStream decryptionStream = new URL(decryptionKeystore).openStream();
try {
ks.load(decryptionStream, smimePw);
} finally {
decryptionStream.close();
}
if (decryptionKeyAlias.equals("")) {
Enumeration e = ks.aliases();
while (e.hasMoreElements()) {
String alias = (String) e.nextElement();
if (ks.isKeyEntry(alias)) {
decryptionKeyAlias = alias;
}
}
if (decryptionKeyAlias.equals(""))
{
throw new Exception("Can't find a private key!");
}
}
//
// find the certificate for the private key and generate a
// suitable recipient identifier.
//
X509Certificate cert = (X509Certificate)ks.getCertificate(decryptionKeyAlias);
if(null == cert) {
throw new Exception("Can't find a key pair with alias \"" + decryptionKeyAlias + "\" in the given keystore");
}
if(verifyCertificate) {
cert.checkValidity();
}
recId = new RecipientId();
recId.setSerialNumber(cert.getSerialNumber());
recId.setIssuer(cert.getIssuerX500Principal().getEncoded());
}
protected String getSystemFileSeparator() {
return System.getProperty("file.separator");
}
protected String getSystemJavaHome() {
return System.getProperty("java.home");
}
protected void processInputs(GetMailMessageInputs getMailMessageInputs) throws Exception {
String strHost = getMailMessageInputs.getHostname();
if (null == strHost || strHost.equals("")) {
throw new Exception(HOST_NOT_SPECIFIED);
} else {
host = strHost.trim();
}
port = getMailMessageInputs.getPort();
protocol = getMailMessageInputs.getProtocol();
String strUsername = getMailMessageInputs.getUsername();
if (null == strUsername || strUsername.equals("")) {
throw new Exception(USERNAME_NOT_SPECIFIED);
} else {
username = strUsername.trim();
}
String strPassword = getMailMessageInputs.getPassword();
if (null == strPassword) {
password = "";
} else {
password = strPassword.trim();
}
String strFolder = getMailMessageInputs.getFolder();
if (null == strFolder || strFolder.equals("")) {
throw new Exception(FOLDER_NOT_SPECIFIED);
} else {
folder = strFolder.trim();
}
String trustAll = getMailMessageInputs.getTrustAllRoots();
// Default value of trustAllRoots is true
trustAllRoots = !(null != trustAll && trustAll.equalsIgnoreCase(STR_FALSE));
String strMessageNumber = getMailMessageInputs.getMessageNumber();
if (strMessageNumber == null || strMessageNumber.equals("")) {
throw new Exception(MESSAGE_NUMBER_NOT_SPECIFIED);
} else {
messageNumber = Integer.parseInt(strMessageNumber);
}
String strSubOnly = getMailMessageInputs.getSubjectOnly();
// Default value of subjectOnly is false
subjectOnly = (strSubOnly != null && strSubOnly.equalsIgnoreCase(STR_TRUE));
String strEnableSSL = getMailMessageInputs.getEnableSSL();
// Default value of enableSSL is false;
enableSSL = (null != strEnableSSL && strEnableSSL.equalsIgnoreCase(STR_TRUE));
String strEnableTLS = getMailMessageInputs.getEnableTLS();
enableTLS = (null != strEnableTLS && strEnableTLS.equalsIgnoreCase(STR_TRUE));
keystore = getMailMessageInputs.getKeystore();
keystorePassword = getMailMessageInputs.getKeystorePassword();
trustKeystoreFile = getMailMessageInputs.getTrustKeystore();
trustPassword = getMailMessageInputs.getTrustPassword();
characterSet = getMailMessageInputs.getCharacterSet();
String strDeleteUponRetrieval = getMailMessageInputs.getDeleteUponRetrieval();
// Default value for deleteUponRetrieval is false
deleteUponRetrieval = (null != strDeleteUponRetrieval && strDeleteUponRetrieval.equalsIgnoreCase(STR_TRUE));
if (messageNumber < 1) {
throw new Exception(MESSAGES_ARE_NUMBERED_STARTING_AT_1);
}
if ((protocol == null || protocol.equals("")) && (port == null || port.equals(""))) {
throw new Exception(PLEASE_SPECIFY_THE_PORT_THE_PROTOCOL_OR_BOTH);
} else if ((protocol != null && !protocol.equals("")) && (!protocol.equalsIgnoreCase(IMAP)) && (!protocol.equalsIgnoreCase(POP3)) && (!protocol.equalsIgnoreCase(IMAP_4))
&& (port == null || port.equals(""))) {
throw new Exception(PLEASE_SPECIFY_THE_PORT_FOR_THE_INDICATED_PROTOCOL);
} else if ((protocol == null || protocol.equals("")) && (port != null && !port.equals(""))
&& (!port.equalsIgnoreCase(IMAP_PORT)) && (!port.equalsIgnoreCase(POP3_PORT))) {
throw new Exception(PLEASE_SPECIFY_THE_PROTOCOL_FOR_THE_INDICATED_PORT);
} else if ((protocol == null || protocol.equals("")) && (port.trim().equalsIgnoreCase(IMAP_PORT))) {
protocol = IMAP;
} else if ((protocol == null || protocol.equals("")) && (port.trim().equalsIgnoreCase(POP3_PORT))) {
protocol = POP3;
} else if ((protocol.trim().equalsIgnoreCase(POP3)) && (port == null || port.equals(""))) {
port = POP3_PORT;
} else if ((protocol.trim().equalsIgnoreCase(IMAP)) && (port == null || port.equals(""))) {
port = IMAP_PORT;
} else if ((protocol.trim().equalsIgnoreCase(IMAP_4)) && (port == null || port.equals(""))) {
port = IMAP_PORT;
}
//The protocol should be given in lowercase to be recognised.
protocol = protocol.toLowerCase();
if (protocol.trim().equalsIgnoreCase(IMAP_4)) {
protocol = IMAP;
}
this.decryptionKeystore = getMailMessageInputs.getDecryptionKeystore();
if(this.decryptionKeystore != null && !this.decryptionKeystore.equals("")) {
if(!decryptionKeystore.startsWith(HTTP)) {
decryptionKeystore = FILE + decryptionKeystore;
}
decryptMessage = true;
decryptionKeyAlias = getMailMessageInputs.getDecryptionKeyAlias();
if(null == decryptionKeyAlias) {
decryptionKeyAlias = "";
}
decryptionKeystorePass = getMailMessageInputs.getDecryptionKeystorePassword();
if(null == decryptionKeystorePass) {
decryptionKeystorePass = "";
}
} else {
decryptMessage = false;
}
String timeout = getMailMessageInputs.getTimeout();
if(timeout != null && !timeout.isEmpty()) {
this.timeout = Integer.parseInt(timeout);
if(this.timeout <= 0) {
throw new Exception("timeout value must be a positive number");
}
this.timeout *= 1000; //timeouts in seconds
}
String verifyCertStr = getMailMessageInputs.getVerifyCertificate();
if(!StringUtils.isEmpty(verifyCertStr)) {
verifyCertificate = Boolean.parseBoolean(verifyCertStr);
}
}
protected Map getMessageByContentTypes(Message message, String characterSet) throws Exception {
Map messageMap = new HashMap<>();
if (message.isMimeType(TEXT_PLAIN)) {
messageMap.put(TEXT_PLAIN, MimeUtility.decodeText(message.getContent().toString()));
} else if (message.isMimeType(TEXT_HTML)) {
messageMap.put(TEXT_HTML, MimeUtility.decodeText(convertMessage(message.getContent().toString())));
}else if (message.isMimeType(MULTIPART_MIXED) || message.isMimeType(MULTIPART_RELATED)) {
messageMap.put(MULTIPART_MIXED, extractMultipartMixedMessage(message, characterSet));
}else {
Object obj = message.getContent();
Multipart mpart = (Multipart) obj;
for (int i = 0, n = mpart.getCount(); i < n; i++) {
Part part = mpart.getBodyPart(i);
if(decryptMessage && part.getContentType() != null && part.getContentType().equals("application/pkcs7-mime; name=\"smime.p7m\"; smime-type=enveloped-data")) {
part = decryptPart((MimeBodyPart)part);
}
String disposition = part.getDisposition();
String partContentType = new String(part.getContentType().substring(0, part.getContentType().indexOf(";")));
if (disposition == null) {
if (part.getContent() instanceof MimeMultipart) { // multipart with attachment
MimeMultipart mm = (MimeMultipart) part.getContent();
for (int j = 0; j < mm.getCount(); j++) {
if (mm.getBodyPart(j).getContent() instanceof String) {
BodyPart bodyPart = mm.getBodyPart(j);
if ((characterSet != null) && (characterSet.trim().length() > 0)) {
String contentType = bodyPart.getHeader(CONTENT_TYPE)[0];
contentType = contentType.replace(contentType.substring(contentType.indexOf("=") + 1), characterSet);
bodyPart.setHeader(CONTENT_TYPE, contentType);
}
String partContentType1 = new String(bodyPart.getContentType().substring(0, bodyPart.getContentType().indexOf(";")));
messageMap.put(partContentType1, MimeUtility.decodeText(bodyPart.getContent().toString()));
}
}
} else {//multipart - w/o attachment
//if the user has specified a certain characterSet we decode his way
if ((characterSet != null) && (characterSet.trim().length() > 0)) {
InputStream istream = part.getInputStream();
ByteArrayInputStream bis = new ByteArrayInputStream(ASCIIUtility.getBytes(istream));
int count = bis.available();
byte[] bytes = new byte[count];
count = bis.read(bytes, 0, count);
messageMap.put(partContentType, MimeUtility.decodeText(new String(bytes, 0, count, characterSet)));
} else {
messageMap.put(partContentType, MimeUtility.decodeText(part.getContent().toString()));
}
}
}
}//for
}//else
return messageMap;
}
private String extractMultipartMixedMessage(Message message, String characterSet) throws Exception {
Object obj = message.getContent();
Multipart mpart = (Multipart) obj;
for (int i = 0, n = mpart.getCount(); i < n; i++) {
Part part = mpart.getBodyPart(i);
if(decryptMessage && part.getContentType() != null && part.getContentType().equals("application/pkcs7-mime; name=\"smime.p7m\"; smime-type=enveloped-data")) {
part = decryptPart((MimeBodyPart)part);
}
String disposition = part.getDisposition();
if (disposition != null) // this means the part is not an inline image or attached file.
continue;
if (part.isMimeType("multipart/related")) { // if related content then check it's parts
String content = processMultipart(part);
if (content != null)
return content;
}
if (part.isMimeType("multipart/alternative")) {
return extractAlternativeContent(part);
}
if (part.isMimeType("text/plain") || part.isMimeType("text/html")) {
return part.getContent().toString();
}
}
return null;
}
private String processMultipart(Part part) throws IOException,
MessagingException {
Multipart relatedparts = (Multipart)part.getContent();
for(int j=0; j < relatedparts.getCount(); j++){
Part rel = relatedparts.getBodyPart(j);
if (rel.getDisposition() == null) { // again, if it's not an image or attachment(only those have disposition not null)
if (rel.isMimeType("multipart/alternative")) { // last crawl through the alternative formats.
return extractAlternativeContent(rel);
}
}
}
return null;
}
private String extractAlternativeContent(Part part) throws IOException,
MessagingException {
Multipart alternatives = (Multipart)part.getContent();
Object content="";
for (int k = 0; k< alternatives.getCount(); k++) {
Part alternative = alternatives.getBodyPart(k);
if (alternative.getDisposition() == null) {
content = alternative.getContent();
}
}
return content.toString();
}
private MimeBodyPart decryptPart(MimeBodyPart part) throws Exception {
SMIMEEnveloped m = new SMIMEEnveloped(part);
RecipientInformationStore recipients = m.getRecipientInfos();
RecipientInformation recipient = recipients.get(recId);
if(null == recipient) {
StringBuilder errorMessage = new StringBuilder();
errorMessage.append("This email wasn't encrypted with \"" + recId.toString() + "\".\n");
errorMessage.append("The encryption recId is: ");
for(Object rec : recipients.getRecipients()) {
if(rec instanceof RecipientInformation) {
RecipientId recipientId = ((RecipientInformation) rec).getRID();
errorMessage.append("\"" + recipientId.toString() + "\"\n");
}
}
throw new Exception(errorMessage.toString());
}
return SMIMEUtil.toMimeBodyPart(recipient.getContent(ks.getKey(decryptionKeyAlias, null), BOUNCY_CASTLE_PROVIDER));
}
protected String getAttachedFileNames(Part part) throws Exception {
String fileNames = "";
Object content = part.getContent();
if (!(content instanceof Multipart)) {
if(decryptMessage && part.getContentType() != null && part.getContentType().equals(ENCRYPTED_CONTENT_TYPE)) {
part = decryptPart((MimeBodyPart) part);
}
// non-Multipart MIME part ...
// is the file name set for this MIME part? (i.e. is it an attachment?)
if (part.getFileName() != null && !part.getFileName().equals("") && part.getInputStream() != null) {
String fileName = part.getFileName();
// is the file name encoded? (consider it is if it's in the =?charset?encoding?encoded text?= format)
if (fileName.indexOf('?') == -1)
// not encoded (i.e. a simple file name not containing '?')-> just return the file name
return fileName;
// encoded file name -> remove any chars before the first "=?" and after the last "?="
return fileName.substring(fileName.indexOf("=?"), fileName.length() -
((new StringBuilder(fileName)).reverse()).indexOf("=?"));
}
} else {
// a Multipart type of MIME part
Multipart mpart = (Multipart) content;
// iterate through all the parts in this Multipart ...
for (int i = 0, n = mpart.getCount(); i < n; i++) {
if (!fileNames.equals(""))
fileNames += STR_COMMA;
// to the list of attachments built so far append the list of attachments in the current MIME part ...
fileNames += getAttachedFileNames(mpart.getBodyPart(i));
}
}
return fileNames;
}
protected String decodeAttachedFileNames(String attachedFileNames) throws Exception {
StringBuilder sb = new StringBuilder();
String delimiter = "";
// splits the input into comma-separated chunks and decodes each chunk according to its encoding ...
for (String fileName : attachedFileNames.split(STR_COMMA)) {
sb.append(delimiter).append(MimeUtility.decodeText(fileName));
delimiter = STR_COMMA;
}
// return the concatenation of the decoded chunks ...
return sb.toString();
}
protected String convertMessage(String msg) throws Exception {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < msg.length(); i++) {
char c = msg.charAt(i);
if (c == '\n') {
sb.append(" ");
} else {
sb.append(c);
}
}
return sb.toString();
}
protected int getFolderOpenMode() {
return Folder.READ_WRITE;
}
/**
* This method addresses the mail headers which contain encoded words. The syntax for an encoded word is defined
* in RFC 2047 section 2: http://www.faqs.org/rfcs/rfc2047.html In some cases the header is marked as having a certain charset
* but at decode not all the characters a properly decoded. This is why it can be useful to force it to decode the text with
* a different charset.
* For example when sending an email using Mozilla Thunderbird and JIS X 0213 characters the subject and attachment headers
* are marked as =?Shift_JIS? but the JIS X 0213 characters are only supported in windows-31j.
*
* This method replaces the charset tag of the header with the new charset provided by the user.
*
* @param header - The header in which the charset will be replaced.
* @param newCharset - The new charset that will be replaced in the given header.
* @return The header with the new charset.
*/
public String changeHeaderCharset(String header, String newCharset) {
return header.replaceAll("=\\?[^\\(\\)<>@,;:/\\[\\]\\?\\.= ]+\\?", "=?" + newCharset + "?"); //match for =?charset?
}
}