package com.softwaremill.common.test.web.email;
import com.dumbster.smtp.SmtpMessage;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.net.QuotedPrintableCodec;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* Class wraps SmtpMessage from mock email server and represents an email message
* with methods to extract certain parts of it.
*
* Available headers might vary, depending on how email was sent.
*
* @author maciek
*/
public class EmailMessage {
private SmtpMessage email;
public EmailMessage(SmtpMessage email) {
this.email = email;
}
public String getSubject(){
return email.getHeaderValue("Subject");
}
/**
* @return Email body, decoded from quoted-printable if such encoding set
*/
public String getMessage(){
if(getHeaderValue(EmailHeader.CONTENT_TRANSFER_ENCODING).equals("quoted-printable")) {
return getDecodedMessage();
} else {
return getRawMessage();
}
}
/**
* @return Raw email body, can be encoded
*/
public String getRawMessage(){
return email.getBody();
}
/**
* @return Decoded email body, null if decoding failed
*/
private String getDecodedMessage() {
String body = removeSoftLineBreaks(email.getBody());
QuotedPrintableCodec codec = new QuotedPrintableCodec();
try {
return codec.decode(body);
} catch (DecoderException e) {
e.printStackTrace();
}
return null;
}
/**
* Removes "soft line breaks" from encoded email.
*
* Email has line length limit to 76 chars - longer lines are split and char '=' is inserted.
* When getting mock email body this line break could appear in th middle of one long line.
* Also this soft line breaks need to be cleared for QuotedPrintableCodec
*
*/
private String removeSoftLineBreaks(String message){
String[] lines = message.split("\n");
StringBuilder sb = new StringBuilder();
for (String line : lines) {
int overflows = (line.length() / 76);
if (overflows > 0) {
int i = 0;
for( ; i < (line.length() / 76); i++) {
sb.append(line.substring(i*76, (i+1)*76 - 1));
}
sb.append(line.substring(i*76));
} else {
sb.append(line);
sb.append("\n");
}
}
return sb.toString();
}
public String getToHeader(){
return email.getHeaderValue("To");
}
public String getFromHeader(){
return email.getHeaderValue("From");
}
public String getHeaderValue(EmailHeader header){
return email.getHeaderValue(header.getValue());
}
public String[] getHeaderValues(EmailHeader header){
return email.getHeaderValues(header.getValue());
}
public String getHeaderValue(String headerName){
return email.getHeaderValue(headerName);
}
public String[] getHeaderValues(String headerName){
return email.getHeaderValues(headerName);
}
public Iterator getHeaderNames() {
return email.getHeaderNames();
}
/**
* Finds all links in email message.
* Does not validate proper url format - finds any http[s]://text-with-no-space
*
* @return List of Strings with found links, or empty list if none found
*/
public List<String> getLinksInMessage() {
List<String> links = new ArrayList<String>();
String msg = getMessage();
Pattern p = Pattern.compile("\\bhttps?[^\\s]*\\b");
Matcher m = p.matcher(msg);
while (m.find()) {
String link = m.group();
links.add(link);
}
return links;
}
/**
* Finds first link in email message with given part
*
* @param urlPart part of url we are looking for, e.g. not changing action part
* @return Url String with matching link, or null if none found
*/
public String getLinkLike(String urlPart) {
for (String link : getLinksInMessage()) {
if (link.contains(urlPart)) {
return link;
}
}
return null;
}
/**
* Finds links in email message with given part
*
* @param urlPart part of url we are looking for, e.g. not changing action part
* @return List of Strings with matching links, or empty list if none found
*/
public List<String> getLinksLike(String urlPart) {
List<String> links = new ArrayList<String>();
for (String link : getLinksInMessage()) {
if (link.contains(urlPart)) {
links.add(link);
}
}
return links;
}
}