package helper; import webutil.Args; import javax.servlet.ServletConfig; import java.util.Properties; import java.util.logging.*; import javax.mail.Session; import javax.mail.Transport; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.internet.InternetAddress; import javax.mail.internet.AddressException; import javax.mail.internet.MimeMessage; import webutil.Util; import webutil.Webmaster; /** * Send simple email from the {@link Webmaster} to a receiver. * *
The emails sent by this class include sender, receiver, subject, and * body. No features such as attachments are supported by this class. If more * flexibity is needed, please use {@link javax.mail} directly. * *
See web.xml for more email configuration information.
*
* @used.By
* {@link TroubleTicket},
* {@link hirondelle.exampleA.user.AddUser}
* {@link hirondelle.exampleA.user.User},
* {@link hirondelle.web4j.Controller}.
*
* @author javapractices.com
* @to.do Is {@link javax.mail.Transport#send} thread-safe? The documentation is not
* clear.
*/
public final class Mailer {
/**
* Called upon startup, to allow this class to extract mail server
* config information from web.xml
.
*/
public static void init(ServletConfig aConfig){
fConfig = aConfig;
}
/**
* Validate the form of an email address.
*
*
Return true
only if
*
aEmailAddress
can successfully construct an
* {@link javax.mail.internet.InternetAddress}
* aEmailAddress
contains
* two tokens which satisfy {@link hirondelle.web4j.util.Util#textHasContent}.
* The second condition arises since local email addresses, simply of the form
* "albert", for example, are valid but almost always undesired.
*/
public static boolean isValidEmailAddress(String aEmailAddress){
if (aEmailAddress == null) return false;
boolean result = true;
try {
InternetAddress emailAddr = new InternetAddress(aEmailAddress);
if ( ! hasNameAndDomain(aEmailAddress) ) {
result = false;
}
}
catch (AddressException ex){
result = false;
}
return result;
}
/**
* Send an email to a single recipient, using the the {@link Webmaster} address
* configured in web.xml
as the "from" address.
*
* @param aToAddress satisfies {@link #isValidEmailAddress}.
* @param aSubject satisfies {@link hirondelle.web4j.util.Util#textHasContent}.
* @param aBody satisfies {@link hirondelle.web4j.util.Util#textHasContent}.
*/
public void send(String aToAddress, String aSubject, String aBody){
Args.checkForContent(aSubject);
Args.checkForContent(aBody);
if ( isMailDisabled() ){
fLogger.fine("Mailing is disabled.");
return;
}
Session session = Session.getDefaultInstance( getMailServerConfig(), null );
MimeMessage message = new MimeMessage( session );
try {
message.setFrom( new InternetAddress(new Webmaster().getEmailAddress()) );
message.addRecipient(Message.RecipientType.TO, new InternetAddress(aToAddress));
message.setSubject( aSubject );
message.setText( aBody );
Transport.send( message ); //thread-safe?
}
catch (MessagingException ex){
fLogger.severe("CANNOT SEND EMAIL." + ex);
}
fLogger.fine("Mail is sent.");
}
// PRIVATE //
private static ServletConfig fConfig;
/**
* Identifies the item in web.xml which contains the configured
* mail server.
*/
private static final String fMAIL_SERVER = "MailServer";
/**
* Identifies the lack of any configured mail server in web.xml.
* If fMAIL_SERVER takes this value, then mailing is disabled, and
* this class will abort all attempts to send email.
*/
private static final String fNONE = "NONE";
private static final Logger fLogger = Util.getLogger(Mailer.class);
private String getMailServer(){
return fConfig.getServletContext().getInitParameter(fMAIL_SERVER);
}
private boolean isMailDisabled(){
return getMailServer().equalsIgnoreCase(fNONE);
}
/**
* Return the configured mail server in the form of a Properties object.
*/
private Properties getMailServerConfig(){
Properties result = new Properties();
result.put("mail.host", getMailServer() );
return result;
}
private static boolean hasNameAndDomain(String aEmailAddress){
String[] tokens = aEmailAddress.split("@");
return
tokens.length == 2 &&
Util.textHasContent( tokens[0] ) &&
Util.textHasContent( tokens[1] ) ;
}
}