package org.subethamail.core.util;
import java.util.logging.Level;
import lombok.extern.java.Log;
/**
* Class which abstracts the handling of VERP bounces. This can
* separate the VERP token from the original address. It can
* also assemble an address from an email and a token.
*
* A VERP'd address looks like:
*
* announce-verp-THISISTHETOKEN-bounce@domain.com
*
* The extracted email will be announce@domain.com.
*
* Note that the token is a lowercase hex-encoded string.
* This is because some evil MTAs (Postfix grrr) force
* the mailbox part of an address to lowercase, screwing
* up any attempt at base64 encoding.
*
* @author Jeff Schnitzer
*/
@Log
public class VERPAddress
{
/** This is the suffix of all VERP'd addresses, plus the '@' */
public static final String SUFFIX = "-b@";
/** This preceeds the token in the address */
public static final String LEAD = "-verp-";
/** */
String email;
String tokenEncoded;
/** */
VERPAddress(String email, String tokenBase62)
{
this.email = email;
this.tokenEncoded = tokenBase62;
}
/**
* @return the "normal" email address, without the verp information.
* This will be the mailing list address that the mail was from.
*/
public String getEmail() { return this.email; }
/**
* Lazily decodes the token.
*
* @return the token that was extracted from the VERP address.
*/
public byte[] getToken()
{
return Base62.decode(this.tokenEncoded);
}
/**
* @return The Base62 encoded string.
*/
public String getRawToken()
{
return this.tokenEncoded;
}
/**
* @return null if the address was not a VERP'ed address.
*/
public static VERPAddress getVERPBounce(String addy)
{
// Note the suffix includes the @
int suffixIndex = addy.indexOf(SUFFIX);
if (suffixIndex < 0)
return null;
int leadIndex = addy.lastIndexOf(LEAD, suffixIndex);
if (leadIndex < 0)
return null;
// Watch out for blah-verp-bounce@foo.bar
if (leadIndex + LEAD.length() >= suffixIndex)
return null;
String email = addy.substring(0, leadIndex) + '@' + addy.substring(suffixIndex+SUFFIX.length());
String tokenBase62 = addy.substring(leadIndex+LEAD.length(), suffixIndex);
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"{0} becomes {1}/{2}", new Object[]{addy,email,tokenBase62});
return new VERPAddress(email, tokenBase62);
}
/**
* @return an email address encoded with the binary token.
*/
public static String encodeVERP(String email, byte[] token)
{
int atIndex = email.indexOf('@');
return email.substring(0, atIndex)
+ LEAD + new String(Base62.encode(token)) + SUFFIX
+ email.substring(atIndex+1);
}
}