/* MessageUtils.java
Copyright (c) 2009 Juergen Schlierf, All Rights Reserved
This file is part of Cubusmail (http://code.google.com/p/cubusmail/).
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with Cubusmail. If not, see <http://www.gnu.org/licenses/>.
*/
package com.cubusmail.mail.util;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.mail.Address;
import javax.mail.FetchProfile;
import javax.mail.Flags;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.UIDFolder;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimePart;
import javax.mail.internet.MimeUtility;
import javax.mail.search.BodyTerm;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.Logger;
import com.sun.mail.imap.IMAPFolder;
import com.cubusmail.core.CubusConstants;
import com.cubusmail.gwtui.domain.MessageListFields;
import com.cubusmail.gwtui.domain.SearchFields;
import com.cubusmail.mail.IMailFolder;
/**
* Util class for general message functions.
*
* @author Juergen Schlierf
*/
public class MessageUtils {
/**
* Type of address string
*
* @author Juergen Schlierf
*/
public enum AddressStringType {
// personal name and Email
COMPLETE,
// personal name or email if therse no personal name
PERSONAL,
// personal name or empty if therse no personal name
PERSONAL_ONLY,
// email only
EMAIL
};
public static final int BUFSIZE = 8192; // 8K
private static Logger log = Logger.getLogger( MessageUtils.class.getName() );
/**
* @param part
* @return
* @throws MessagingException
*/
public static boolean isImagepart( Part part ) throws MessagingException {
return part.isMimeType( "image/png" ) || part.isMimeType( "image/gif" ) || part.isMimeType( "image/jpg" )
|| part.isMimeType( "image/jpeg" );
}
/**
* @param emailAddress
* @param displayName
* @return
*/
public static String toInternetAddress( String emailAddress, String displayName ) {
InternetAddress address;
try {
if ( !StringUtils.isEmpty( displayName ) ) {
address = new InternetAddress( emailAddress, displayName );
return address.toUnicodeString();
}
else {
return emailAddress;
}
}
catch (UnsupportedEncodingException e) {
return null;
}
}
/**
* Parses the adresslist.
*
* @param addresslist
* @param charset
* @return
*/
public static InternetAddress[] parseInternetAddress( String addresslist, String charset )
throws MessagingException {
if ( addresslist != null ) {
addresslist = addresslist.replace( ';', ',' );
InternetAddress[] addressArray = InternetAddress.parse( addresslist );
if ( addressArray != null ) {
for (InternetAddress address : addressArray) {
String personal = address.getPersonal();
if ( personal != null ) {
try {
address.setPersonal( personal, charset );
}
catch (UnsupportedEncodingException e) {
log.error( e.getMessage(), e );
}
}
}
}
return addressArray;
}
return null;
}
/**
* Format the date.
*
* @param date
* @return
*/
public static String formatMailDate( Date date ) {
if ( date != null ) {
DateFormat format = SimpleDateFormat.getDateTimeInstance( SimpleDateFormat.MEDIUM, SimpleDateFormat.SHORT,
Locale.GERMAN );
return format.format( date );
}
else {
return "";
}
}
/**
* Format the size of a part like message or attachment.
*
* @param size
* @return
*/
public static String formatPartSize( int size, NumberFormat format ) {
String value = null;
if ( size >= 1024 ) {
value = format.format( size / 1024 ) + " KB";
}
else {
if ( size > 0 ) {
value = Integer.toString( size ) + " B";
}
else {
value = "n/a";
}
}
return value;
}
/**
* @param locale
* @return
*/
public static NumberFormat createSizeFormat( Locale locale ) {
NumberFormat sizeFormat = DecimalFormat.getNumberInstance( locale );
sizeFormat.setGroupingUsed( true );
sizeFormat.setMaximumFractionDigits( 0 );
sizeFormat.setMinimumFractionDigits( 0 );
return sizeFormat;
}
/**
* Calculate the real size bytes.
*
* @param orgSize
* @return
*/
public static int calculateAttachmentSize( int orgSize ) {
if ( orgSize > 0 ) {
double size = (double) orgSize;
size = size * CubusConstants.MESSAGE_SIZE_FACTOR;
return (int) Math.round( size );
}
return orgSize;
}
/**
* @param addressArray
* @param emailAddress
* @return
*/
public static boolean findEmailAddress( Address[] addressArray, Address addressToFind ) {
if ( addressArray != null ) {
for (Address address : addressArray) {
if ( address.equals( addressToFind ) ) {
return true;
}
}
}
return false;
}
/**
* @param msg
* @return
* @throws MessagingException
*/
public static boolean isHtmlMessage( Message msg ) throws MessagingException {
return msg.isMimeType( "text/html" );
}
/**
* Method for checking if the message has attachments.
*/
public static List<MimePart> attachmentsFromPart( Part part ) throws MessagingException, IOException {
List<MimePart> attachmentParts = new ArrayList<MimePart>();
if ( part instanceof MimePart ) {
MimePart mimePart = (MimePart) part;
if ( part.isMimeType( "multipart/*" ) ) {
Multipart mp = (Multipart) mimePart.getContent();
for (int i = 0; i < mp.getCount(); i++) {
MimeBodyPart bodyPart = (MimeBodyPart) mp.getBodyPart( i );
if ( Part.ATTACHMENT.equals( bodyPart.getDisposition() )
|| Part.INLINE.equals( bodyPart.getDisposition() ) ) {
attachmentParts.add( bodyPart );
}
}
}
else if ( part.isMimeType( "application/*" ) ) {
attachmentParts.add( mimePart );
}
}
return attachmentParts;
}
/**
* @param part
* @return
* @throws MessagingException
* @throws IOException
*/
public static boolean hasAttachments( Part part ) throws MessagingException, IOException {
try {
if ( part.isMimeType( "multipart/*" ) ) {
Multipart mp = (Multipart) part.getContent();
for (int i = 0; i < mp.getCount(); i++) {
MimeBodyPart bodyPart = (MimeBodyPart) mp.getBodyPart( i );
if ( Part.ATTACHMENT.equals( bodyPart.getDisposition() )
|| Part.INLINE.equals( bodyPart.getDisposition() ) ) {
return true;
}
}
}
}
catch (Exception e) {
log.error( e.getMessage(), e );
}
return false;
}
/**
* @param addressArray
* @param personalOnly
* @return
* @throws MessagingException
*/
public static String getMailAdressString( Address[] addressArray, AddressStringType type )
throws MessagingException {
String addressString = "";
if ( addressArray != null ) {
for (int i = 0; i < addressArray.length; i++) {
String address = getMailAdressString( addressArray[i], type );
if ( i < (addressArray.length - 1) ) {
addressString += address + ", ";
}
else {
addressString += address;
}
}
}
else {
addressString = "";
}
return addressString;
}
/**
* @param address
* @param personalOnly
* @return
* @throws MessagingException
*/
public static String getMailAdressString( Address address, AddressStringType type ) throws MessagingException {
String addressString = null;
if ( type == AddressStringType.PERSONAL || type == AddressStringType.PERSONAL_ONLY ) {
addressString = ((InternetAddress) address).getPersonal();
if ( StringUtils.isEmpty( addressString ) && type == AddressStringType.PERSONAL ) {
addressString = ((InternetAddress) address).getAddress();
}
}
else if ( type == AddressStringType.COMPLETE ) {
addressString = ((InternetAddress) address).toUnicodeString();
}
else if ( type == AddressStringType.EMAIL ) {
addressString = ((InternetAddress) address).getAddress();
}
return addressString;
}
/**
* @param data
* @return
*/
public static String decodeText( String data ) {
int start = 0, i;
StringBuffer sb = new StringBuffer();
while ((i = data.indexOf( "=?", start )) >= 0) {
sb.append( data.substring( start, i ) );
int end = data.indexOf( "?=", i );
if ( end < 0 ) {
break;
}
String s = data.substring( i, end + 2 );
try {
sb.append( MimeUtility.decodeWord( s ) );
}
catch (Exception e) {
sb.append( s );
}
start = end + 2;
}
if ( start == 0 )
return data;
if ( start < data.length() )
sb.append( data.substring( start ) );
return sb.toString();
}
/**
* @param msg
* @param flag
* @param readFlag
* @throws MessagingException
*/
public static void setMessageFlag( Message msg, Flags.Flag flag, boolean readFlag ) throws MessagingException {
boolean currentFlag = msg.isSet( flag );
if ( currentFlag != readFlag ) {
msg.setFlag( flag, readFlag );
}
}
/**
* @param msg
* @return
* @throws MessagingException
*/
public static boolean isMessageReadFlag( Message msg ) throws MessagingException {
return msg.isSet( Flags.Flag.SEEN );
}
/**
*
*
* @param msg
* @return
*/
public static int getMessagePriority( Message msg ) {
int prio = CubusConstants.PRIORITY_NONE;
try {
String header[] = msg.getHeader( CubusConstants.FETCH_ITEM_PRIORITY );
if ( header != null && header.length > 0 && header[0].length() > 0 ) {
String first = header[0].substring( 0, 1 );
if ( StringUtils.isNumeric( first ) ) {
return Integer.parseInt( first );
}
}
}
catch (MessagingException e) {
log.error( e.getMessage(), e );
}
return prio;
}
/**
* Sort the messages.
*
* @param fieldName
* @param ascending
*/
public static void sortMessages( Message[] msgs, String fieldName, boolean ascending ) {
if ( msgs != null && msgs.length > 0 ) {
if ( !StringUtils.isEmpty( fieldName ) ) {
Arrays.sort( msgs, new MessageComparator( fieldName, ascending ) );
}
else {
// reverse order
ArrayUtils.reverse( msgs );
}
}
}
/**
* Filter the messages.
*
* @param msgs
* @param searchFields
* @param searchText
* @return
*/
public static Message[] quickFilterMessages( Message[] msgs, String searchFields, String searchText ) {
if ( !StringUtils.isEmpty( searchFields ) && !StringUtils.isEmpty( searchText ) ) {
searchFields = StringUtils.remove( searchFields, '[' );
searchFields = StringUtils.remove( searchFields, ']' );
searchFields = StringUtils.remove( searchFields, '\"' );
String[] fields = StringUtils.split( searchFields, ',' );
List<Message> filteredMsgs = new ArrayList<Message>();
Date searchDate = null;
try {
searchDate = DateUtils.parseDate( searchText, new String[] { "dd.MM.yyyy" } );
}
catch (Exception e) {
// do nothing
}
try {
for (Message message : msgs) {
boolean contains = false;
for (String searchField : fields) {
if ( MessageListFields.SUBJECT.name().equals( searchField ) ) {
String subject = message.getSubject();
contains = StringUtils.containsIgnoreCase( subject, searchText );
}
else if ( MessageListFields.FROM.name().equals( searchField ) ) {
String from = MessageUtils.getMailAdressString( message.getFrom(),
AddressStringType.COMPLETE );
contains = StringUtils.containsIgnoreCase( from, searchText ) || contains;
}
else if ( searchDate != null && MessageListFields.DATE.name().equals( searchField ) ) {
Date sendDate = message.getSentDate();
contains = (sendDate != null && DateUtils.isSameDay( searchDate, sendDate )) || contains;
}
}
if ( contains ) {
filteredMsgs.add( message );
}
}
}
catch (MessagingException ex) {
log.warn( ex.getMessage(), ex );
}
return filteredMsgs.toArray( new Message[0] );
}
return msgs;
}
/**
* @param mailFolder
* @param msgs
* @param extendedSearchFields
* @param params
* @return
*/
public static Message[] filterMessages( IMailFolder mailFolder, Message[] msgs, String extendedSearchFields,
String[][] params ) {
if ( !StringUtils.isEmpty( extendedSearchFields ) ) {
String[] fields = StringUtils.split( extendedSearchFields, ',' );
List<Message> filteredMsgs = new ArrayList<Message>();
String fromValue = getParamValue( params, SearchFields.FROM.name() );
String toValue = getParamValue( params, SearchFields.TO.name() );
String ccValue = getParamValue( params, SearchFields.CC.name() );
String subjectValue = getParamValue( params, SearchFields.SUBJECT.name() );
String contentValue = getParamValue( params, SearchFields.CONTENT.name() );
String dateFromValue = getParamValue( params, SearchFields.DATE_FROM.name() );
String dateToValue = getParamValue( params, SearchFields.DATE_TO.name() );
try {
// Body search
if ( StringUtils.contains( extendedSearchFields, SearchFields.CONTENT.name() ) ) {
BodyTerm term = new BodyTerm( contentValue );
msgs = mailFolder.search( term, msgs );
if ( msgs == null ) {
msgs = new Message[0];
}
}
for (Message message : msgs) {
boolean contains = true;
for (String searchField : fields) {
if ( SearchFields.FROM.name().equals( searchField ) ) {
String from = MessageUtils.getMailAdressString( message.getFrom(),
AddressStringType.COMPLETE );
contains = StringUtils.containsIgnoreCase( from, fromValue );
}
if ( contains && SearchFields.TO.name().equals( searchField ) ) {
String to = MessageUtils.getMailAdressString( message
.getRecipients( Message.RecipientType.TO ), AddressStringType.COMPLETE );
if ( !StringUtils.isEmpty( to ) ) {
contains = StringUtils.containsIgnoreCase( to, toValue );
}
else {
contains = false;
}
}
if ( contains && SearchFields.CC.name().equals( searchField ) ) {
String cc = MessageUtils.getMailAdressString( message
.getRecipients( Message.RecipientType.CC ), AddressStringType.COMPLETE );
if ( !StringUtils.isEmpty( cc ) ) {
contains = StringUtils.containsIgnoreCase( cc, ccValue );
}
else {
contains = false;
}
}
if ( contains && SearchFields.SUBJECT.name().equals( searchField ) ) {
if ( !StringUtils.isEmpty( message.getSubject() ) ) {
contains = StringUtils.containsIgnoreCase( message.getSubject(), subjectValue );
}
else {
contains = false;
}
}
if ( contains && SearchFields.DATE_FROM.name().equals( searchField ) ) {
Date dateFrom = new Date( Long.parseLong( dateFromValue ) );
if ( message.getSentDate() != null ) {
contains = !message.getSentDate().before( dateFrom );
}
else {
contains = false;
}
}
if ( contains && SearchFields.DATE_TO.name().equals( searchField ) ) {
Date dateTo = new Date( Long.parseLong( dateToValue ) );
if ( message.getSentDate() != null ) {
contains = !message.getSentDate().after( dateTo );
}
else {
contains = false;
}
}
}
if ( contains ) {
filteredMsgs.add( message );
}
}
}
catch (MessagingException ex) {
log.warn( ex.getMessage() );
}
return filteredMsgs.toArray( new Message[0] );
}
return msgs;
}
/**
* @param complete
* @param sortfield
* @return
*/
public static FetchProfile createFetchProfile( boolean complete, String sortfield ) {
FetchProfile fp = new FetchProfile();
if ( complete ) {
fp.add( FetchProfile.Item.ENVELOPE );
fp.add( FetchProfile.Item.FLAGS );
fp.add( FetchProfile.Item.CONTENT_INFO );
fp.add( IMAPFolder.FetchProfileItem.SIZE );
fp.add( CubusConstants.FETCH_ITEM_PRIORITY );
fp.add( UIDFolder.FetchProfileItem.UID );
}
else {
if ( sortfield != null ) {
if ( MessageListFields.ATTACHMENT_FLAG.name().equals( sortfield ) ) {
fp.add( FetchProfile.Item.CONTENT_INFO );
}
else if ( MessageListFields.SUBJECT.name().equals( sortfield )
|| MessageListFields.FROM.name().equals( sortfield )
|| MessageListFields.TO.name().equals( sortfield )
|| MessageListFields.DATE.name().equals( sortfield ) ) {
fp.add( FetchProfile.Item.ENVELOPE );
}
else if ( MessageListFields.SIZE.name().equals( sortfield ) ) {
fp.add( IMAPFolder.FetchProfileItem.SIZE );
}
}
}
return fp;
}
/**
* @param params
* @param paramName
* @return
*/
public static String getParamValue( String[][] params, String paramName ) {
String result = null;
if ( params != null ) {
for (int i = 0; i < params.length; i++) {
if ( params[i] != null && params[i].length == 2 && paramName.equals( params[i][0] ) ) {
return params[i][1];
}
}
}
return result;
}
}