public class EmailTemplate extends Object
A directory within the classpath should be created, and filled with the following files:
Concerning languages, although e.g. "subject.utf8.txt" must be present, there may also be files with names such as "subject_de.utf8.txt" files for other Locales.
One or both of the plain-text and HTML versions of the email must be present. If they are both present then a "multipart/alternative" email is sent.
The templates are Velocity templates meaning that variables like ${XYZ}
can be used.
Velocity supports #foreach
etc.
For variables in HTML files use $esc.html($xyz)
.
For unit testing, use the static method setLastBodyForTestingInsteadOfSendingEmails()
.
After that method has been called, no emails will be sent,
instead the method getLastBodyForTesting()
may be used to retrieve the last sent plain/text email body.
This allows one to assert that particular emails would be sent, and that they contain particular text.
For testing with e.g. Litmus (tools to test your emails across the many email clients),
the facility writeHtmlPartToFile(Locale, URL, Map, File)
exists.
Emails can be written to disk as opposed to sent, in order that the real email that would be sent can be uploaded to
Litmus for testing, without any velocity template commands, and with real user data.
Writing code such as new EmailTemplate("myproject.mtpl.registration")
has the disadvantage that if that package is renamed, refactoring tools will not see this string, and not rename it. Errors will result at run-time. The solution is to create a class in the directory, which calls its superclass constructor with its package name. This class is then instanciated in the client code, instead of the general EmailTemplate
.
You can send attachments with your email (e.g. PDF invoices) by passing multiple EmailTemplate.Attachment
objects to the send method.
Either you implement your own attachment, providing the filename, mime type and a way to get an InputStream for the bytes of the attachment,
or you can just create a EmailTemplate.ByteArrayAttachment
by passing the filename, mime type and a byte[]
.
Concerning naming,
In the directory containing the template files:
class RegistrationEmailTemplate extends EmailTemplate { public RegistrationEmailTemplate() { super(RegistrationEmailTemplate.class.getPackage()); } // other methods can be added, specific to this email template }
In client code:
class RegistrationProcess { public registerNewUser(InternetAddress emailAddress, Locale language, String name, ... ) { String smtpServer = "localhost"; EmailTransaction tx = new EmailTransaction(smtpServer); Map<String,String> params = new HashMap<String,String>(); params.put("USERNAME", name); RegistrationEmailTemplate tpl = new RegistrationEmailTemplate(); tpl.send(tx, recipientEmailAddress, language, params); tx.commit(); } }
In unit test code:
class RegistrationProcessTest extends TestCase { public testRegisterNewUser() { EmailTemplate.setLastBodyForTestingInsteadOfSendingEmails(); new RegistrationProcess().registerNewUser("test@example.com", "Adrian"); String txt = EmailTemplate.getLastBodyForTesting(); assertTrue(txt.contains("Adrian")); } }
Modifier and Type | Class and Description |
---|---|
static interface |
EmailTemplate.Attachment |
static class |
EmailTemplate.ByteArrayAttachment |
static class |
EmailTemplate.FileNotFoundInEmailTemplateDirectoryException |
Constructor and Description |
---|
EmailTemplate(Package pkg) |
EmailTemplate(String pkgStr) |
Modifier and Type | Method and Description |
---|---|
String |
getCampaignName()
Gets the "campaign name" (or "category" or "tag") which is sent along with this email when it's delivered.
|
static String |
getLastBodyForTesting()
Return the plain text body of the last email which has been sent; or the empty string in case no emails have been sent.
|
static javax.mail.BodyPart |
newAttachmentBodyPart(EmailTemplate.Attachment attachment) |
void |
send(EmailTransaction tx,
Collection<javax.mail.internet.InternetAddress> recipientEmailAddresses,
Locale locale,
Map<String,? extends Object> parameters,
EmailTemplate.Attachment... attachments)
Send an email based on this email template.
|
void |
send(EmailTransaction tx,
javax.mail.internet.InternetAddress recipientEmailAddress,
Locale locale,
Map<String,? extends Object> parameters,
EmailTemplate.Attachment... attachments) |
static void |
setLastBodyForTestingInsteadOfSendingEmails()
Henceforth, no emails will be sent; instead the body will be recorded for inspection by
getLastBodyForTesting() . |
void |
writeHtmlPartToFile(Locale locale,
URL imageBaseUrl,
Map<String,? extends Object> parameters,
File file) |
public EmailTemplate(Package pkg)
public EmailTemplate(String pkgStr)
public static javax.mail.BodyPart newAttachmentBodyPart(EmailTemplate.Attachment attachment) throws javax.mail.MessagingException
javax.mail.MessagingException
public static void setLastBodyForTestingInsteadOfSendingEmails()
getLastBodyForTesting()
.public static String getLastBodyForTesting()
public void send(EmailTransaction tx, Collection<javax.mail.internet.InternetAddress> recipientEmailAddresses, Locale locale, Map<String,? extends Object> parameters, EmailTemplate.Attachment... attachments)
public void send(EmailTransaction tx, javax.mail.internet.InternetAddress recipientEmailAddress, Locale locale, Map<String,? extends Object> parameters, EmailTemplate.Attachment... attachments)
public void writeHtmlPartToFile(Locale locale, URL imageBaseUrl, Map<String,? extends Object> parameters, File file)
imageBaseUrl
- images in the directory must be uploaded somewhere. They are then replaced
in the HTML with a link to that place.file
- where to write the HTML topublic String getCampaignName()
By default it is the package name of the email template.
Sometimes it can be useful to have a tag which is sent along with an email, for example SendGrid can then do reports based on that. If the email is sent via default SMTP then this is ignored. Currently only SendGridEmailTransaction makes use of this.