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

jodd.mail.EmailUtil Maven / Gradle / Ivy

There is a newer version: 7.1.0
Show newest version
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

package jodd.mail;

import jakarta.mail.Authenticator;
import jakarta.mail.Flags;
import jakarta.mail.MessagingException;
import jakarta.mail.NoSuchProviderException;
import jakarta.mail.Part;
import jakarta.mail.Session;
import jakarta.mail.Store;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeUtility;
import jodd.util.CharUtil;
import jodd.util.StringPool;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Properties;
import java.util.function.Consumer;

/**
 * Email utilities.
 */
public class EmailUtil {

	protected static final String ATTR_CHARSET = "charset=";
	static final String NO_NAME = "no-name";

	/**
	 * Extracts MIME type from content type.
	 *
	 * @param contentType MIME type.
	 * @return MIME type for the given content type.
	 */
	//TODO: should this always return lowercase or always uppercase?
	public static String extractMimeType(final String contentType) {
		final int ndx = contentType.indexOf(';');
		final String mime;
		if (ndx != -1) {
			mime = contentType.substring(0, ndx);
		} else {
			mime = contentType;
		}
		return mime;
	}

	/**
	 * Extracts encoding from a given content type.
	 *
	 * @param contentType content type.
	 * @return Encoding from the content type. May return {@code null} if encoding is not specified in content type.
	 */
	//TODO: should this always return lowercase or always uppercase?
	public static String extractEncoding(final String contentType) {
		int ndx = contentType.indexOf(';');
		final String charset = ndx != -1 ? contentType.substring(ndx + 1) : StringPool.EMPTY;
		String encoding = null;

		ndx = charset.indexOf(ATTR_CHARSET);
		if (ndx != -1) {
			ndx += ATTR_CHARSET.length();
			final int len = charset.length();

			if (charset.charAt(ndx) == '"') {
				ndx++;
			}
			final int start = ndx;

			while (ndx < len) {
				final char c = charset.charAt(ndx);
				if ((c == '"') || (CharUtil.isWhitespace(c)) || (c == ';')) {
					break;
				}
				ndx++;
			}
			encoding = charset.substring(start, ndx);
		}
		return encoding;
	}

	/**
	 * Extracts encoding from a given content type.
	 *
	 * @param contentType     content type.
	 * @param defaultEncoding Default encoding to be used if extract returns {@code null}.
	 *                        If defaultEncoding is {@code null}, default encoding will be used.
	 * @return Encoding from the content type.
	 * @see #extractEncoding(String)
	 */
	public static String extractEncoding(final String contentType, String defaultEncoding) {
		String encoding = extractEncoding(contentType);

		if (encoding == null) {
			if (defaultEncoding == null) {
				defaultEncoding = "UTF-8";
			}
			encoding = defaultEncoding;
		}
		return encoding;
	}

	/**
	 * Correctly resolves file name from the message part.
	 * Thanx to: Flavio Pompermaier
	 *
	 * @param part {@link Part} to decode file name from.
	 * @return String containing file name.
	 */
	public static String resolveFileName(final Part part) throws MessagingException {
		if (!(part instanceof MimeBodyPart)) {
			return part.getFileName();
		}

		final String contentType = part.getContentType();
		String ret;

		try {
			ret = MimeUtility.decodeText(part.getFileName());
		} catch (final Exception ex) {
			// String[] contentId = part.getHeader("Content-ID");
			// if (contentId != null && contentId.length > 0) {
			final String contentId = ((MimeBodyPart) part).getContentID();
			if (contentId != null) {
				ret = contentId + contentTypeForFileName(contentType);
			} else {
				ret = defaultFileName(contentType);
			}
		}

		return ret;
	}

	private static String contentTypeForFileName(final String contentType) {
		return StringPool.DOT + contentType.substring(contentType.lastIndexOf("/") + 1, contentType.length());
	}

	private static String defaultFileName(final String contentType) {
		return NO_NAME + contentTypeForFileName(contentType);
	}

	/**
	 * @param protocol          Protocol such as {@link ImapServer#PROTOCOL_IMAP} or {@link Pop3Server#PROTOCOL_POP3}.
	 * @param sessionProperties Session properties to use.
	 * @param authenticator     Authenticator which contains necessary authentication for server.
	 * @param debugConsumer
	 * @return {@link ReceiveMailSession}.
	 */
	public static ReceiveMailSession createSession(final String protocol, final Properties sessionProperties, final Authenticator authenticator, final File attachmentStorage, final Consumer debugConsumer) {
		final Session session = Session.getInstance(sessionProperties, authenticator);
		if (debugConsumer != null) {
			session.setDebugOut(new PrintStream(new ByteArrayOutputStream() {
				@Override
				public void flush() throws IOException {
					final String record;
					synchronized (this) {
						super.flush();
						record = this.toString().trim();
						super.reset();

						if (record.length() == 0 || record.equals(System.lineSeparator())) {
							// avoid empty records
							return;
						}

						debugConsumer.accept(record);
					}
				}
			}, true));
		}
		final Store store;
		try {
			store = session.getStore(protocol);
		} catch (final NoSuchProviderException nspex) {
			final String errMsg = String.format("Failed to create %s session", protocol);
			throw new MailException(errMsg, nspex);
		}
		return new ReceiveMailSession(session, store, attachmentStorage);
	}

	/**
	 * Check whether flags is a empty flags
	 *
	 * @param flags a flags of message to check
	 * @return whether the flags is empty
	 */
	public static boolean isEmptyFlags(final Flags flags) {
		if (flags == null) {
			return true;
		}
		final Flags.Flag[] systemFlags = flags.getSystemFlags();
		if (systemFlags != null && systemFlags.length > 0) {
			return false;
		}
		final String[] userFlags = flags.getUserFlags();
		if (userFlags != null && userFlags.length > 0) {
			return false;
		}

		return true;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy