/*
* $Id$
* $URL$
*/
package org.subethamail.common;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
/**
* Offers static utility methods to help processing javamail
* objects.
*
* @author Jeff Schnitzer
*/
public class MailUtils
{
/** Matches stuff like (without the quotes): "Re[1][3]: Aw: Sv[3]: " */
public static final Pattern SUBJECT_PATTERN = Pattern.compile("((RE|AW|SV)(\\[\\d+\\])*:\\s*)+", Pattern.CASE_INSENSITIVE);
/** default constructor prevents util class from being created. */
private MailUtils() {}
/**
* Returns the specified line with any From_ line encoding removed.
*/
public static String decodeMboxFrom(String line)
{
if (line != null)
{
int len = line.length();
for (int i = 0; i < (len - 5); i++)
{
char c = line.charAt(i);
if (i > 0
&& (c == 'F' && line.charAt(i + 1) == 'r' && line.charAt(i + 2) == 'o'
&& line.charAt(i + 3) == 'm' && line.charAt(i + 4) == ' '))
return line.substring(1);
if (c != '>') break;
}
}
return line;
}
/**
* Returns the email address in the From_ line.
*/
public static String getMboxFrom(String line)
{
String prettyLine = decodeMboxFrom(line);
String[] parts = prettyLine.split(" ");
if (prettyLine.indexOf('@')>0)
{
return parts[1];
}
for (int i = 0; i < parts.length; i++)
{
String s = parts[i];
if("at".equals(s))
return parts[i-1] + "@" + parts[i+1];
}
return null;
}
/**
* Assumes that the contentType contains a name header in
* the form of quoted value ('name="thename"')
* semicolon ended value ('name=name;'), or newline
* ended value ('name=name \n')
*
* Note: A null argument creates an exception.
*
* @param contentType the contentType string
* @return the name
*/
public static String getNameFromContentType(String contentType)
{
// null contentType results an exception
if (contentType == null) throw new IllegalArgumentException();
// figure out the name, if there is one.
String name = "";
int namestart = contentType.indexOf("name=");
if (namestart > 0)
{
// add the number of chars in 'name='
namestart += "name=".length();
int endnamevalue = contentType.indexOf("\"", namestart + 1);
// we have a quoted value
if (endnamevalue > namestart) return contentType.substring(namestart + 1, endnamevalue);
endnamevalue = contentType.indexOf(";", namestart);
// we have a ; ended value
if (endnamevalue > namestart) return contentType.substring(namestart, endnamevalue);
endnamevalue = contentType.indexOf("\n", namestart);
// we have a newline ended value, maybe with whitespace
if (endnamevalue > namestart) return contentType.substring(namestart, endnamevalue).trim();
}
return name;
}
/**
* @return a rfc222-compliant comma-separated list of addresses, or
* null if no from field was available.
*/
public static String getFrom(Message msg) throws MessagingException
{
Address[] froms = msg.getFrom();
if (froms == null || froms.length == 0)
return null;
if (froms.length == 1)
{
return froms[0].toString();
}
else
{
StringBuffer buf = new StringBuffer();
for (int i=0; i<froms.length; i++)
{
if (i != 0)
buf.append(", ");
buf.append(froms[i].toString());
}
return buf.toString();
}
}
/**
* FIXME: This documentation needs revision, what does this method do?!?
*
* Converts: Re: Re: Foo to Re: Foo
* @param subject the subject message
* @param prefix null or the stuff in the []... Re: [List Name] Subject
* @param isReply if you know this is a reply, then always append Re:
* @return A perfect subject.
*/
public static String cleanRe(String subject, String prefix, boolean isReply)
{
if (prefix == null)
prefix = new String();
Matcher matcher = SUBJECT_PATTERN.matcher(subject);
String result = null;
if (matcher.find())
{
subject = subject.substring(matcher.end());
result = "Re: " + prefix + subject;
}
else
{
if (isReply)
result = "Re: " + prefix + subject;
else
result = prefix + subject;
}
return result;
}
/**
* Removes Re: and friends from the beginning of a subject line.
* @param subject a subject that might or might not start with reply prefixes.
*
* @return the subject without the reply prefixes.
*/
public static String cleanRe(String subject)
{
Matcher matcher = SUBJECT_PATTERN.matcher(subject);
if (matcher.find())
{
return subject.substring(matcher.end());
}
else
{
return subject;
}
}
/**
* Pass in either a comma and/or newline separated list of emails and it returns a list of InternetAddress
* @param input
* @return the internet addresses contained in the text input
* @throws AddressException if there is an error parsing the emails.
*/
public static InternetAddress[] parseMassSubscribe(String input) throws AddressException
{
String[] split = input.split("[\r\n\t]");
List<InternetAddress> list = new ArrayList<InternetAddress>();
for (String token : split)
{
token = token.trim();
if (token.length() > 0)
{
InternetAddress[] addresses = InternetAddress.parse(token);
for (InternetAddress address : addresses)
{
list.add(address);
}
}
}
return list.toArray(new InternetAddress[list.size()]);
}
}