All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nervousync.utils.MailUtils Maven / Gradle / Ivy

There is a newer version: 1.2.1
Show newest version
/*
 * Licensed to the Nervousync Studio (NSYC) 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.nervousync.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.*;

import jakarta.activation.DataHandler;
import jakarta.activation.DataSource;
import jakarta.activation.FileDataSource;
import jakarta.mail.*;
import jakarta.mail.internet.*;
import jakarta.mail.util.ByteArrayDataSource;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute;
import org.bouncycastle.asn1.smime.SMIMECapability;
import org.bouncycastle.asn1.smime.SMIMECapabilityVector;
import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cms.SignerInfoGenerator;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationVerifier;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
import org.bouncycastle.mail.smime.SMIMEException;
import org.bouncycastle.mail.smime.SMIMESignedGenerator;
import org.bouncycastle.mail.smime.SMIMESignedParser;
import org.bouncycastle.mail.smime.SMIMEUtil;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.eclipse.angus.mail.imap.IMAPFolder;
import org.eclipse.angus.mail.pop3.POP3Folder;
import org.nervousync.enumerations.mail.MailProtocol;
import org.nervousync.mail.MailObject;
import org.nervousync.mail.authenticator.DefaultAuthenticator;
import org.nervousync.mail.config.MailConfig;
import org.nervousync.mail.operator.ReceiveOperator;
import org.nervousync.mail.operator.SendOperator;
import org.nervousync.mail.protocol.impl.IMAPProtocol;
import org.nervousync.mail.protocol.impl.POP3Protocol;
import org.nervousync.mail.protocol.impl.SMTPProtocol;
import org.nervousync.commons.core.Globals;
import org.nervousync.security.factory.SecureFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The type Mail utils.
 *
 * @author Steven Wee     [email protected]
 * @version $Revision : 1.0 $ $Date: Jul 31, 2012 8:54:04 PM $
 */
public final class MailUtils {

    private MailUtils() {
    }

    /**
     * Initialize a new mail agent by given mail config
     *
     * @param mailConfig Mail config
     * @return Optional instance of generated mail agent or empty Option instance if mail config is invalid
     */
    public static Agent mailAgent(final MailConfig mailConfig) {
        if (mailConfig == null || StringUtils.isEmpty(mailConfig.getUserName())
                || StringUtils.isEmpty(mailConfig.getPassword())) {
            return null;
        }
        return new Agent(mailConfig);
    }

    /**
     * The type Agent.
     */
    public static final class Agent {

        private final Logger logger = LoggerFactory.getLogger(this.getClass());

        private final String userName;
        private final String passWord;
        private final MailConfig.ServerConfig sendConfig;
        private final SendOperator sendOperator;
        private final MailConfig.ServerConfig receiveConfig;
        private final ReceiveOperator receiveOperator;
        private final String storagePath;
        private final X509Certificate x509Certificate;
        private final PrivateKey privateKey;

        private Agent(final MailConfig mailConfig) {
            this.userName = mailConfig.getUserName().toLowerCase();
            this.passWord = SecureFactory.getInstance().decrypt(mailConfig.getSecureName(), mailConfig.getPassword());
            if (mailConfig.getSendConfig() == null
                    || !MailProtocol.SMTP.equals(mailConfig.getSendConfig().getProtocolOption())) {
                this.sendConfig = null;
                this.sendOperator = null;
            } else {
                this.sendConfig = mailConfig.getSendConfig();
                this.sendOperator = new SMTPProtocol(mailConfig.getSecureName(), mailConfig.getProxyConfig());
            }
            if (mailConfig.getReceiveConfig() == null) {
                this.receiveConfig = null;
                this.receiveOperator = null;
            } else {
                this.receiveConfig = mailConfig.getReceiveConfig();
                switch (this.receiveConfig.getProtocolOption()) {
                    case IMAP:
                        this.receiveOperator = new IMAPProtocol(mailConfig.getSecureName(), mailConfig.getProxyConfig());
                        break;
                    case POP3:
                        this.receiveOperator = new POP3Protocol(mailConfig.getSecureName(), mailConfig.getProxyConfig());
                        break;
                    default:
                        this.receiveOperator = null;
                        break;
                }
            }
            this.storagePath = mailConfig.getStoragePath();
            this.x509Certificate = StringUtils.notBlank(mailConfig.getCertificate())
                    ? CertificateUtils.x509(StringUtils.base64Decode(mailConfig.getCertificate()))
                    : null;
            this.privateKey = StringUtils.notBlank(mailConfig.getPrivateKey())
                    ? CertificateUtils.privateKey("RSA", StringUtils.base64Decode(mailConfig.getPrivateKey()))
                    : null;
        }

        /**
         * Send mail boolean.
         *
         * @param mailObject the mail object
         * @return the boolean
         */
        public boolean sendMail(final MailObject mailObject) {
            if (this.sendOperator == null) {
                //	Not config send server
                return Boolean.FALSE;
            }
            try {
                Properties properties = this.sendOperator.readConfig(this.sendConfig);
                if (StringUtils.notBlank(this.userName)) {
                    properties.setProperty("mail.smtp.from", this.userName);
                }
                Session session =
                        Session.getDefaultInstance(properties, new DefaultAuthenticator(this.userName, this.passWord));
                session.setDebug(this.logger.isDebugEnabled());
                if (StringUtils.isEmpty(mailObject.getSendAddress())) {
                    mailObject.setSendAddress(this.userName);
                }
                Transport.send(convert(session, mailObject, this.x509Certificate, this.privateKey));
                return Boolean.TRUE;
            } catch (MessagingException e) {
                this.logger.error("Send mail failed!");
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Stack message: ", e);
                }
                return Boolean.FALSE;
            }
        }

        public List folderList() {
            List folderList = new ArrayList<>();
            try (Store store = connect()) {
                Optional.ofNullable(store.getDefaultFolder())
                        .ifPresent(defaultFolder -> {
                            try {
                                Optional.ofNullable(defaultFolder.list()).map(Arrays::asList)
                                        .ifPresent(folders ->
                                                folders.forEach(folder -> folderList.add(folder.getFullName())));
                            } catch (MessagingException e) {
                                if (this.logger.isDebugEnabled()) {
                                    this.logger.debug("Read folder list error! ", e);
                                }
                            }
                        });
            } catch (Exception e) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Read folder list error! ", e);
                }
            }
            return folderList;
        }

        /**
         * Mail count int.
         *
         * @return the int
         */
        public int mailCount() {
            return this.mailCount(Globals.DEFAULT_EMAIL_FOLDER_INBOX);
        }

        /**
         * Mail count int.
         *
         * @param folderName the folder name
         * @return the int
         */
        public int mailCount(final String folderName) {
            if (this.receiveOperator == null) {
                //	Not configs receive server
                return Globals.DEFAULT_VALUE_INT;
            }
            try (Store store = connect(); Folder folder = openReadOnlyFolder(store, folderName)) {
                if (folder.exists() && folder.isOpen()) {
                    return folder.getMessageCount();
                }
            } catch (Exception e) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Receive Message Error! ", e);
                }
            }
            return Globals.DEFAULT_VALUE_INT;
        }

        /**
         * Mail list.
         *
         * @return the list
         */
        public List mailList() {
            return this.mailList(Globals.DEFAULT_EMAIL_FOLDER_INBOX);
        }

        /**
         * Mail list.
         *
         * @param folderName the folder name
         * @return the list
         */
        public List mailList(final String folderName) {
            return mailList(folderName, Globals.DEFAULT_VALUE_INT, Globals.DEFAULT_VALUE_INT);
        }

        /**
         * Mail list.
         *
         * @param folderName the folder name
         * @param begin      the beginning index
         * @param end        the end index
         * @return the list
         */
        public List mailList(final String folderName, final int begin, final int end) {
            if (this.receiveOperator == null || end < begin) {
                return Collections.emptyList();
            }

            try (Store store = connect(); Folder folder = openReadOnlyFolder(store, folderName)) {
                if (!folder.exists() || !folder.isOpen()) {
                    return Collections.emptyList();
                }

                int totalCount = folder.getMessageCount();
                List mailList = new ArrayList<>();
                int start = Math.max(1, begin);
                int stop = (end < 0) ? totalCount : Math.min(totalCount, end);
                for (Message message : folder.getMessages(start, stop)) {
                    mailList.add(this.receiveOperator.readUID(folder, message));
                }
                return mailList;
            } catch (Exception e) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Receive Message Error! ", e);
                }
            }
            return Collections.emptyList();
        }

        /**
         * Read mail optional.
         *
         * @param folderName the folder name
         * @param uid        the uid
         * @return the optional
         */
        public Optional readMail(final String folderName, final String uid) {
            return this.readMail(folderName, uid, Boolean.FALSE);
        }

        /**
         * Read mail optional.
         *
         * @param folderName the folder name
         * @param uid        the uid
         * @param detail     read mail detail
         * @return the optional
         */
        public Optional readMail(final String folderName, final String uid, final boolean detail) {
            if (this.receiveOperator == null) {
                return Optional.empty();
            }
            try (Store store = connect(); Folder folder = openReadOnlyFolder(store, folderName)) {
                if (!folder.exists() || !folder.isOpen()) {
                    return Optional.empty();
                }

                Message message = this.receiveOperator.readMessage(folder, uid);
                if (message != null) {
                    return receiveMessage((MimeMessage) message, detail);
                }
            } catch (Exception e) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Receive Message Error! ", e);
                }
            }

            return Optional.empty();
        }

        /**
         * Read the mail list.
         *
         * @param folderName the folder name
         * @param uidArrays  the uid arrays
         * @return the list
         */
        public List readMailList(final String folderName, final String... uidArrays) {
            List mailList = new ArrayList<>();
            if (this.receiveOperator == null) {
                return mailList;
            }

            try (Store store = connect(); Folder folder = openReadOnlyFolder(store, folderName)) {
                if (!folder.exists() || !folder.isOpen()) {
                    return mailList;
                }
                this.receiveOperator.readMessages(folder, uidArrays)
                        .forEach(message ->
                                receiveMessage((MimeMessage) message, Boolean.FALSE)
                                        .ifPresent(mailList::add));
            } catch (Exception e) {
                this.logger.error("Receive Message Error! ");
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Stack message: ", e);
                }
            }

            return mailList;
        }

        /**
         * Set mails status as read by uid list
         *
         * @param folderName the folder name
         * @param uidArrays  the uid arrays
         * @return the boolean
         */
        public boolean readMails(final String folderName, final String... uidArrays) {
            return this.flagMailsStatus(Flags.Flag.SEEN, Boolean.TRUE, folderName, uidArrays);
        }

        /**
         * Set mails status as unread by uid list
         *
         * @param folderName the folder name
         * @param uidArrays  the uid arrays
         * @return the boolean
         */
        public boolean unreadMails(final String folderName, final String... uidArrays) {
            return this.flagMailsStatus(Flags.Flag.SEEN, Boolean.FALSE, folderName, uidArrays);
        }

        /**
         * Set mails status as answered by uid list
         *
         * @param folderName the folder name
         * @param uidArrays  the uid arrays
         * @return the boolean
         */
        public boolean answerMails(final String folderName, final String... uidArrays) {
            return this.flagMailsStatus(Flags.Flag.ANSWERED, Boolean.TRUE, folderName, uidArrays);
        }

        /**
         * Set mails status as deleted by uid list
         *
         * @param folderName the folder name
         * @param uidArrays  the uid arrays
         * @return the boolean
         */
        public boolean deleteMails(final String folderName, final String... uidArrays) {
            return this.flagMailsStatus(Flags.Flag.DELETED, Boolean.TRUE, folderName, uidArrays);
        }

        /**
         * Set mails status as not deleted by uid list
         *
         * @param folderName the folder name
         * @param uidArrays  the uid arrays
         * @return the boolean
         */
        public boolean recoverMails(final String folderName, final String... uidArrays) {
            if (this.receiveOperator == null) {
                return Boolean.FALSE;
            }
            try (Store store = connect(); Folder folder = openFolder(store, Boolean.FALSE, folderName);
                 Folder inbox = openFolder(store, Boolean.FALSE, Globals.DEFAULT_EMAIL_FOLDER_INBOX)) {
                if (!folder.exists() || !folder.isOpen()) {
                    return Boolean.FALSE;
                }

                List messageList = this.receiveOperator.readMessages(folder, uidArrays);

                folder.copyMessages(messageList.toArray(new Message[0]), inbox);
                return true;
            } catch (Exception e) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Set message status error! ", e);
                }
                return Boolean.FALSE;
            }
        }

        /**
         * Set mails status as flagged by uid list
         *
         * @param folderName the folder name
         * @param uidArrays  the uid arrays
         * @return the boolean
         */
        public boolean flagMails(final String folderName, final String... uidArrays) {
            return this.flagMailsStatus(Flags.Flag.FLAGGED, Boolean.TRUE, folderName, uidArrays);
        }

        /**
         * Set mails status as not flagged by uid list
         *
         * @param folderName the folder name
         * @param uidArrays  the uid arrays
         * @return the boolean
         */
        public boolean unflagMails(final String folderName, final String... uidArrays) {
            return this.flagMailsStatus(Flags.Flag.FLAGGED, Boolean.FALSE, folderName, uidArrays);
        }

        /**
         * Flag mails boolean.
         *
         * @param flag      the flag
         * @param status    the status
         * @param uidArrays the uid arrays
         * @return the boolean
         */
        private boolean flagMailsStatus(final Flags.Flag flag, final boolean status,
                                        final String folderName, final String... uidArrays) {
            if (this.receiveOperator == null) {
                return Boolean.FALSE;
            }
            try (Store store = connect(); Folder folder = openFolder(store, Boolean.FALSE, folderName)) {

                if (!folder.exists() || !folder.isOpen()) {
                    return Boolean.FALSE;
                }

                List messageList = this.receiveOperator.readMessages(folder, uidArrays);

                for (Message message : messageList) {
                    message.setFlag(flag, status);
                }
                return true;
            } catch (Exception e) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Set message status error! ", e);
                }
                return Boolean.FALSE;
            }
        }

        /**
         * Connect to mail server
         *
         * @return Store instance
         * @throws MessagingException connect failed
         */
        private Store connect() throws MessagingException {
            Properties properties = this.receiveOperator.readConfig(this.receiveConfig);
            Session session =
                    Session.getInstance(properties, new DefaultAuthenticator(this.userName, this.passWord));
            session.setDebug(this.logger.isDebugEnabled());

            Store store = session.getStore(properties.getProperty("mail.store.protocol"));

            store.connect(this.receiveConfig.getHostName(), this.receiveConfig.getHostPort(),
                    this.userName, this.passWord);
            return store;
        }

        @SuppressWarnings("unchecked")
        private boolean verifyMessage(final MimeMessage mimeMessage) {
            try {
                MimeMessage signedMessage = new MimeMessage(mimeMessage);
                SMIMESignedParser signedParser;
                if (signedMessage.isMimeType("multipart/signed")) {
                    signedParser = new SMIMESignedParser(new JcaDigestCalculatorProviderBuilder().build(),
                            (MimeMultipart) signedMessage.getContent());
                } else if (signedMessage.isMimeType("application/pkcs7-mime")) {
                    signedParser = new SMIMESignedParser(new JcaDigestCalculatorProviderBuilder().build(), signedMessage);
                } else {
                    return Boolean.TRUE;
                }

                org.bouncycastle.util.Store certificates = signedParser.getCertificates();
                for (SignerInformation signerInformation : signedParser.getSignerInfos().getSigners()) {
                    Collection certCollection = certificates.getMatches(signerInformation.getSID());
                    X509Certificate certificate =
                            new JcaX509CertificateConverter().setProvider("BC")
                                    .getCertificate((X509CertificateHolder) certCollection.iterator().next());

                    try {
                        SignerInformationVerifier signerInformationVerifier =
                                new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(certificate);
                        return signerInformation.verify(signerInformationVerifier);
                    } catch (Exception e) {
                        if (this.logger.isDebugEnabled()) {
                            this.logger.debug("Verify signature failed! ", e);
                        }
                    }
                }
            } catch (Exception e) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Verify signature failed! ", e);
                }
            }
            return Boolean.FALSE;
        }

        /**
         * Read mail info
         *
         * @param mimeMessage MIME message instance
         * @param detail      read detail
         * @return Mail object instance
         */
        private Optional receiveMessage(final MimeMessage mimeMessage, final boolean detail) {
            if (!verifyMessage(mimeMessage)) {
                return Optional.empty();
            }
            try {
                MailObject mailObject = new MailObject();
                List receiveList = new ArrayList<>();
                Address[] allRecipients = mimeMessage.getAllRecipients();
                if (allRecipients == null) {
                    return Optional.empty();
                }
                Arrays.stream(allRecipients)
                        .filter(InternetAddress.class::isInstance)
                        .forEach(address -> receiveList.add(((InternetAddress) address).getAddress().toLowerCase()));
                if (!receiveList.contains(this.userName)) {
                    throw new MessagingException("Current account not in receive list! ");
                }

                mailObject.setReceiveAddress(receiveList);

                Folder folder = mimeMessage.getFolder();

                if (folder instanceof POP3Folder) {
                    mailObject.setUid(((POP3Folder) folder).getUID(mimeMessage));
                } else if (folder instanceof IMAPFolder) {
                    mailObject.setUid(Long.valueOf(((IMAPFolder) folder).getUID(mimeMessage)).toString());
                }
                String subject = mimeMessage.getSubject();

                if (StringUtils.notBlank(subject)) {
                    mailObject.setSubject(MimeUtility.decodeText(subject));
                } else {
                    mailObject.setSubject(Globals.DEFAULT_VALUE_STRING);
                }
                mailObject.setSendDate(mimeMessage.getSentDate());
                mailObject.setSendAddress(MimeUtility.decodeText(InternetAddress.toString(mimeMessage.getFrom())));

                if (detail) {
                    //	Read mail cc address
                    Optional.ofNullable((InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.CC))
                            .ifPresent(ccAddress -> {
                                List ccList = new ArrayList<>();
                                Arrays.asList(ccAddress).forEach(address -> ccList.add(address.getAddress()));
                                mailObject.setCcAddress(ccList);
                            });

                    //	Read mail bcc address
                    Optional.ofNullable((InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.BCC))
                            .ifPresent(bccAddress -> {
                                List bccList = new ArrayList<>();
                                Arrays.asList(bccAddress).forEach(address -> bccList.add(address.getAddress()));
                                mailObject.setBccAddress(bccList);
                            });

                    //	Read mail content message
                    StringBuilder contentBuffer = new StringBuilder();
                    getMailContent(mimeMessage, contentBuffer);
                    mailObject.setContent(contentBuffer.toString());
                    mailObject.setContentType(mimeMessage.getContentType());

                    mailObject.setAttachFiles(getMailAttachment(mimeMessage));
                }

                return Optional.of(mailObject);
            } catch (MessagingException | IOException e) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Receive message error! ", e);
                }
                return Optional.empty();
            }
        }

        private List getMailAttachment(final Part part) throws MessagingException, IOException {
            List saveFiles = new ArrayList<>();
            if (StringUtils.isEmpty(this.storagePath)) {
                throw new IOException("Save attach file path error! ");
            }
            if (part.isMimeType(Globals.DEFAULT_EMAIL_CONTENT_TYPE_MULTIPART)) {
                Multipart multipart = (Multipart) part.getContent();
                int count = multipart.getCount();
                for (int i = 0; i < count; i++) {
                    Optional.ofNullable(multipart.getBodyPart(i))
                            .ifPresent(bodyPart -> this.readBodyPart(bodyPart, saveFiles));
                }
            }
            return saveFiles;
        }

        private void readBodyPart(final Part bodyPart, final List saveFiles) {
            try {
                if (bodyPart.getHeader("Content-ID") != null
                        && bodyPart.getHeader("Content-ID").length > 0) {
                    return;
                }
                if (StringUtils.notBlank(bodyPart.getFileName())) {
                    String disposition = bodyPart.getDisposition();
                    if (disposition != null
                            && (disposition.equals(Part.ATTACHMENT) || disposition.equals(Part.INLINE))) {
                        String savePath = this.storagePath + Globals.DEFAULT_PAGE_SEPARATOR
                                + MimeUtility.decodeText(bodyPart.getFileName());
                        if (!savePath.toLowerCase().endsWith("p7s")) {
                            boolean saveFile = FileUtils.saveFile(bodyPart.getInputStream(), savePath);
                            if (saveFile) {
                                saveFiles.add(savePath);
                            }
                        }
                    } else if (bodyPart.isMimeType(Globals.DEFAULT_EMAIL_CONTENT_TYPE_MULTIPART)) {
                        saveFiles.addAll(getMailAttachment(bodyPart));
                    }
                }
            } catch (MessagingException | IOException e) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Receive attaches file error! ", e);
                }
            }
        }
    }

    private static MimeMessage convert(final Session session, final MailObject mailObject,
                                       final X509Certificate x509Certificate, final PrivateKey privateKey)
            throws MessagingException {
        MimeMessage message = new MimeMessage(session);

        message.setSubject(mailObject.getSubject(), mailObject.getCharset());

        MimeMultipart mimeMultipart = new MimeMultipart();

        if (mailObject.getAttachFiles() != null) {
            for (String attachment : mailObject.getAttachFiles()) {
                MimeBodyPart mimeBodyPart = new MimeBodyPart();

                File file;

                try {
                    file = FileUtils.getFile(attachment);
                } catch (FileNotFoundException e) {
                    throw new MessagingException("Attachment file not found! ", e);
                }

                DataSource dataSource = new FileDataSource(file);

                mimeBodyPart.setFileName(StringUtils.getFilename(attachment));
                mimeBodyPart.setDataHandler(new DataHandler(dataSource));

                mimeMultipart.addBodyPart(mimeBodyPart, mimeMultipart.getCount());
            }
        }

        if (mailObject.getIncludeFiles() != null) {
            List includeFiles = mailObject.getIncludeFiles();
            for (String filePath : includeFiles) {
                File file;
                MimeBodyPart mimeBodyPart;

                try {
                    file = FileUtils.getFile(filePath);
                    String fileName = StringUtils.getFilename(filePath);
                    mimeBodyPart = new MimeBodyPart();
                    DataHandler dataHandler =
                            new DataHandler(new ByteArrayDataSource(file.toURI().toURL().openStream(),
                                    "application/octet-stream"));
                    mimeBodyPart.setDataHandler(dataHandler);

                    mimeBodyPart.setFileName(fileName);
                    mimeBodyPart.setHeader("Content-ID", fileName);
                } catch (Exception e) {
                    throw new MessagingException("Process include file error! ", e);
                }

                mimeMultipart.addBodyPart(mimeBodyPart, mimeMultipart.getCount());
            }
        }

        if (StringUtils.notBlank(mailObject.getContent())) {
            MimeBodyPart mimeBodyPart = new MimeBodyPart();
            mimeBodyPart.setContent(mailObject.getContent(),
                    mailObject.getContentType() + "; charset=" + mailObject.getCharset());
            mimeMultipart.addBodyPart(mimeBodyPart, mimeMultipart.getCount());
        }

        if (x509Certificate != null && privateKey != null) {
            message.setContent(mimeMultipart);
            try {
                //  Generate signature attribute
                ASN1EncodableVector signatureAttribute = new ASN1EncodableVector();
                SMIMECapabilityVector capabilityVector = new SMIMECapabilityVector();
                capabilityVector.addCapability(SMIMECapability.aES256_CBC);
                capabilityVector.addCapability(SMIMECapability.dES_CBC);
                capabilityVector.addCapability(SMIMECapability.rC2_CBC, 128);
                signatureAttribute.add(new SMIMECapabilitiesAttribute(capabilityVector));
                signatureAttribute.add(new SMIMEEncryptionKeyPreferenceAttribute(SMIMEUtil.createIssuerAndSerialNumberFor(x509Certificate)));

                List certificateList = Collections.singletonList(x509Certificate);
                JcaCertStore certStore = new JcaCertStore(certificateList);

                SignerInfoGenerator signerInfoGenerator = new JcaSimpleSignerInfoGeneratorBuilder()
                        .setProvider("BC")
                        .setSignedAttributeGenerator(new AttributeTable(signatureAttribute))
                        .build("SHA1withRSA", privateKey, x509Certificate);

                SMIMESignedGenerator generator = new SMIMESignedGenerator();
                generator.addSignerInfoGenerator(signerInfoGenerator);
                generator.addCertificates(certStore);

                MimeMultipart signedMimeMultipart = generator.generate(message);
                message.setContent(signedMimeMultipart, signedMimeMultipart.getContentType());
            } catch (CertificateEncodingException | CertificateParsingException | OperatorCreationException |
                     SMIMEException e) {
                throw new MessagingException("Signature mail error! ", e);
            }
        } else {
            message.setContent(mimeMultipart, mimeMultipart.getContentType());
        }

        message.setFrom(new InternetAddress(mailObject.getSendAddress()));

        if (mailObject.getReceiveAddress() == null || mailObject.getReceiveAddress().isEmpty()) {
            throw new MessagingException("Unknown receive address");
        }
        StringBuilder receiveAddress = new StringBuilder();
        mailObject.getReceiveAddress().forEach(address -> receiveAddress.append(",").append(address));
        message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(receiveAddress.substring(1)));

        if (mailObject.getCcAddress() != null && !mailObject.getCcAddress().isEmpty()) {
            StringBuilder ccAddress = new StringBuilder();
            mailObject.getCcAddress().forEach(address -> ccAddress.append(",").append(address));
            message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(ccAddress.substring(1)));
        }

        if (mailObject.getBccAddress() != null && !mailObject.getBccAddress().isEmpty()) {
            StringBuilder bccAddress = new StringBuilder();
            mailObject.getBccAddress().forEach(address -> bccAddress.append(",").append(address));
            message.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(bccAddress.substring(1)));
        }

        if (mailObject.getReplyAddress() != null && !mailObject.getReplyAddress().isEmpty()) {
            StringBuilder replyAddress = new StringBuilder();
            mailObject.getReplyAddress().forEach(address -> replyAddress.append(",").append(address));
            message.setReplyTo(InternetAddress.parse(replyAddress.substring(1)));
        } else {
            message.setReplyTo(InternetAddress.parse(mailObject.getSendAddress()));
        }
        message.setSentDate(mailObject.getSendDate() == null ? new Date() : mailObject.getSendDate());
        return message;
    }

    private static Folder openReadOnlyFolder(final Store store, final String folderName)
            throws MessagingException {
        return openFolder(store, Boolean.TRUE, folderName);
    }

    private static Folder openFolder(final Store store, final boolean readOnly, final String folderName)
            throws MessagingException {
        Folder folder = store.getFolder(folderName);
        folder.open(readOnly ? Folder.READ_ONLY : Folder.READ_WRITE);
        return folder;
    }

    private static void getMailContent(final Part part, final StringBuilder contentBuffer)
            throws MessagingException, IOException {
        String contentType = part.getContentType();
        int nameIndex = contentType.indexOf("name");

        if (contentBuffer == null) {
            throw new IOException();
        }

        if (part.isMimeType(Globals.DEFAULT_EMAIL_CONTENT_TYPE_TEXT) && (nameIndex == -1)) {
            contentBuffer.append(part.getContent().toString());
        } else if (part.isMimeType(Globals.DEFAULT_EMAIL_CONTENT_TYPE_HTML) && (nameIndex == -1)) {
            contentBuffer.append(part.getContent().toString());
        } else if (part.isMimeType(Globals.DEFAULT_EMAIL_CONTENT_TYPE_MULTIPART)) {
            Multipart multipart = (Multipart) part.getContent();
            int count = multipart.getCount();
            for (int i = 0; i < count; i++) {
                getMailContent(multipart.getBodyPart(i), contentBuffer);
            }
        } else if (part.isMimeType(Globals.DEFAULT_EMAIL_CONTENT_TYPE_MESSAGE_RFC822)) {
            getMailContent((Part) part.getContent(), contentBuffer);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy