Class MailServerExtension
- All Implemented Interfaces:
ReportFactoryExtension
The MailServerExtension offers a standard way to access email messages, using the "imap" URL schema described in RFC5092.
Authentication is now rarely done with usernames and password alone,
so this class makes use of the KeyStore
class, to store
authorization data as a SecretKey
. This will work with any
JCE or JCEKS format keystore (although PKCS12 may not work). This
isn't a necessary part of the API, but it is a convenient and
secure way to store the arbitrary authorization data required for
IMAP authentication.
The example below is a complete example showing how this works. A KeyStore is specified, and will be created if it doesn't exist.
// First create the extension and add it to the ReportFactory
ReportFactory factory = new ReportFactory();
MailServerExtension ext = new MailServerExtension(factory);
factory.getReportFactoryExtensions().add(ext);
String username = "user@example.com";
char[] password = "secret".toCharArray();
// Configure the extension to use a particular keystore,
// then load the authorization data from it. If it's not
// there or the keystore is missing, create the authorization
// data then save it to the keystore for next time.
ext.setKeyStore(Paths.get("keystore.jceks"), password, "jceks", null);
Json json = ext.load(username, password);
if (json == null) {
// First time login.
MailServerExtension.GMailHelper gmail = new MailServerExtension.GMailHelper();
gmail.setEmail(username);
gmail.setClientId("NNNNN.apps.googleusercontent.com");
gmail.setClientSecret("NNNNN");
gmail.setRedirectURI("http://127.0.0.1:8000/oauth");
json = ext.save(username, password, gmail.create());
}
URL2 uri = ext.createStore(json);
Store store = ext.getStore(uri);
// We are now connected to the IMAP server. To convert a message to PDF:
// Option 1 - load message via the object directly
Folder folder = store.getFolder(foldername);
if (!folder.isOpen()) {
folder.open(Folder.READ_ONLY);
}
Message message = folder.getMessage(num);
Report report = factory.createReport();
report.load(message);
// Option 2 - load message via an "imap" URL
URL2 msguri = uri.resolve("/"+folderName+"/;uid="+((UIDFolder)folder).getUID(message));
report.load(msguri);
The JSON configuration
The configuration for connecting to mail server is represented as a JSON object. The intention is this class will ship with various helpers to configure output for common mail service providers, and if one is available for your service that's what we recommend. Otherwise, a JSON object can be created manually. The fields are:
- scheme - the Mail URL scheme, should always be
"imap"
- store -the store type, should always be
"imaps"
- email -the email address being accessed
- server -the email server address, eg
"imap.gmail.com"
- properties -an optional map of strings used configure the Java IMAP connection. A typical example would be
{"mail.imap.auth.mechanisms":"XOAUTH2","mail.imaps.sasl.enable":"true"}}
- auth - a map containing the authorization details - it should contain a
type
string anddata
, a map of values specific to the authorizer. For OAUTH2 authorization,auth.type
should be"oauth2"
, andauth.data
a map as described in theOAuth2
class.
Here is a full example of a configuration for the Google "Gmail" service,
as generated by the MailServerExtension.GMailHelper
class.
{
"scheme": "imap",
"server": "imap.gmail.com",
"store": "imaps",
"email": "test@example.org",
"properties": {
"mail.imap.auth.mechanisms": "XOAUTH2",
"mail.imaps.sasl.enable": "true"
},
"auth": {
"type": "oauth2",
"data": {
"auth_uri": "https://accounts.google.com/o/oauth2/v2/auth",
"token_uri": "https://www.googleapis.com/oauth2/v4/token",
"redirect_uri": "http://127.0.0.1:8080/oauth",
"client_id": "nnnnnnnn.apps.googleusercontent.com",
"client_secret": "nnnnnnnn",
"scope": "https://mail.google.com/",
"protocol": {
"auth": {
"prompt": "consent"
}
},
}
},
}
This class requires the javax.mail.internet
package to be available on the classpath.-
Nested Class Summary
Modifier and TypeClassDescriptionstatic class
A static helper class that allows easy creation of configuration for loading messages from Google Mail -
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionvoid
configure
(Json j) Configure the extension.createStore
(Json json) Given a Json configuration, connect to the IMAP server it defines and return a URL which can be used to access that Store.Return the properties used by this class, as set bysetProperties(java.util.Properties)
Store
Return a Store matching the specified URL.Json
Load a configuration from the KeyStore set withsetKeyStore(java.nio.file.Path, char[], java.lang.String, java.security.Provider)
and saved withsave(java.lang.String, char[], Json)
void
register
(ReportFactory factory) Notify this object it has beem added to a ReportFactory.void
removeStore
(URL2 uri) Remove a Store matching the specified URL.Json
Save a configuration to the KeyStore set withsetKeyStore(java.nio.file.Path, char[], java.lang.String, java.security.Provider)
.void
setKeyStore
(Path file, char[] storepass, String type, Provider provider) Set the KeyStore to be used with theload(java.lang.String, char[])
andsave(java.lang.String, char[], Json)
methodsvoid
setKeyStore
(KeyStore keystore) Set the KeyStore to be used with theload(java.lang.String, char[])
andsave(java.lang.String, char[], Json)
methodsvoid
setProperties
(Properties properties) Set the set of properties to be used with this class.void
unregister
(ReportFactory factory) Notify this object it has been removed from a ReportFactory.Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Methods inherited from interface org.faceless.publisher.ext.ReportFactoryExtension
load, register, unregister
-
Constructor Details
-
MailServerExtension
public MailServerExtension() -
MailServerExtension
-
-
Method Details
-
register
Description copied from interface:ReportFactoryExtension
Notify this object it has beem added to a ReportFactory. Will be called when this object is added to the list returned byReportFactory.getReportFactoryExtensions()
. The default implementation is a no-op.- Specified by:
register
in interfaceReportFactoryExtension
-
unregister
Description copied from interface:ReportFactoryExtension
Notify this object it has been removed from a ReportFactory. Will be called when this object is removed from the list returned byReportFactory.getReportFactoryExtensions()
. The default implementation is a no-op.- Specified by:
unregister
in interfaceReportFactoryExtension
-
configure
public void configure(Json j) Description copied from interface:ReportFactoryExtension
Configure the extension. This method will be called by the web-service immediately after the extension is added, to pass in any parameters set by the user. The default implementation does nothing- Specified by:
configure
in interfaceReportFactoryExtension
-
load
Load a configuration from the KeyStore set withsetKeyStore(java.nio.file.Path, char[], java.lang.String, java.security.Provider)
and saved withsave(java.lang.String, char[], Json)
- Parameters:
alias
- the alias the configuration is saved aspassword
- the password the configuration was saved with- Returns:
- the configuration
- Throws:
IOException
GeneralSecurityException
-
save
public Json save(String alias, char[] password, Json json) throws IOException, NoSuchAlgorithmException, KeyStoreException, CertificateException Save a configuration to the KeyStore set with
setKeyStore(java.nio.file.Path, char[], java.lang.String, java.security.Provider)
. The configuration is saved as a "secret key" with a custom type, and so requires a KeyStore that can handle secret keys - JKS or JCEKS (and explicitly not PKCS#12). Saving a configuration in this way offers an easy secure way to store login details with the same level of security as any other cryptographic material used by Java.- Parameters:
alias
- the alias the configuration is saved aspassword
- the password the configuration was saved withjson
- the configuration to save.- Returns:
- the json parameter
- Throws:
IOException
NoSuchAlgorithmException
KeyStoreException
CertificateException
-
setProperties
Set the set of properties to be used with this class. Defaults toSystem.getProperties()
- Parameters:
properties
- the properties
-
getProperties
Return the properties used by this class, as set bysetProperties(java.util.Properties)
- Returns:
- the properties
-
setKeyStore
public void setKeyStore(Path file, char[] storepass, String type, Provider provider) throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException Set the KeyStore to be used with theload(java.lang.String, char[])
andsave(java.lang.String, char[], Json)
methods- Parameters:
file
- the path to the KeyStorestorepass
- the KeyStore store passwordtype
- the KeyStore type, typically "jce" or "jceks"provider
- if not null, the Provider to use to create the KeyStore object- Throws:
IOException
KeyStoreException
NoSuchAlgorithmException
CertificateException
-
setKeyStore
Set the KeyStore to be used with theload(java.lang.String, char[])
andsave(java.lang.String, char[], Json)
methods- Parameters:
keystore
- the KeyStore
-
createStore
Given a Json configuration, connect to the IMAP server it defines and return a URL which can be used to access that Store.- Parameters:
json
- the Json configuration- Returns:
- the base URL
- Throws:
IOException
GeneralSecurityException
MessagingException
-
getStore
Return a Store matching the specified URL. The URL should have been created by callingcreateStore(Json)
- Parameters:
uri
- the uri- Returns:
- the Store, or
null
if there's no match
-
removeStore
Remove a Store matching the specified URL. The URL should have been created by callingcreateStore(Json)
- Parameters:
uri
- the uri
-