#### Example: E-mailing billing reports

Sometimes, sending pertinent report data to corresponding mail recipients is required. JReport Enterprise Server allows you to send a scheduled report result to the e-mail addresses accordingly, based on the page-level security settings of the report and the user information stored in JReport Enterprise Server (e.g. e-mail address information). Therefore, each recipient will only be able to view certain parts of the report data. However, using e-mail information of server users is not reliable, since a user ID that is appropriate for the report doesn't always exist in JReport Enterprise Server. In cases like this, the mails will not be sent successfully. The best way to resolve this is to use an external e-mail information source by implementing the UserMailList and UserMailListFactory API that JReport provides.

JReport provides two interfaces for you to retrieve user and e-mail information from a customized source:

- jet.server.api.UserMailListFactory
  Used to get the UserMailList instance implemented by the user.
- jet.server.api.UserMailList
  Used to get e-mail information from a customized source.

You can implement multiple classes of interface UserMailList. Each of them may refer to a particular report. By using the getInstance() method in the jet.server.api.UserMailListFactory interface, you can get one implementation of the UserMailList. For more information on these two interfaces, see JReport Server API Documentation.

The following is a simple example:

1. Here, there is a Customers table with customer names and their e-mail addresses, as illustrated below. You can design a report using this table and others. Then apply page-level security for this report, so that later in the server side, you can schedule the report and send pertinent data to different recipients saved in this Customers table.

2. In JReport Designer, design a report and set the page-level security for it. In this case, group the report data by Customer Name, and then grant a formula FPageLevel to it. The content of the formula FPageLevel is as below:

   `@"Customer Name";`

   This means that only the records of the specified group will be shown at runtime when you enter with different IDs -- Customer Name, in this example.

3. Then in the server side, implement the two interfaces to import the e-mail lists saved in the Customers table. Specifically, implement the jet.server.api.UserMailListFactory interface. The getInstance() method should be implemented in this interface to get an instance of jet.server.api.UserMailList. Take the following implementation as a reference, where the implementing class name of the UserMailList interface is formatted as "UserMailList_" + report + "_Impl", such as "UserMailList_InvoiceReport_cls_Impl".

       import jet.server.api.*;
       import jet.cs.util.*;
       public class DemoUserMailListFactoryImpl implements UserMailListFactory {
       public UserMailList getInstance(ServerInfo serverInfo) {
       if (serverInfo == null) {
       return null;
       }
       String rpt = null;
       try {
       rpt = serverInfo.getTaskProperties().getProperty(APIConst.TAG_REPORT);
       } catch (RptServerException e) {
       e.printStackTrace();
       return null;
       }
       rpt = rpt.substring(rpt.lastIndexOf("/") + 1);
       rpt = rpt.replace('.', '_');
       rpt = rpt.replace(' ', '_');
       String clsName = "UserMailList_" + rpt + "_Impl";
       try {
       UserMailList mailList = (UserMailList)Class.forName(clsName).newInstance();
       return mailList;
       } catch (InstantiationException e1) {
       e1.printStackTrace();
       } catch (IllegalAccessException e1) {
       e1.printStackTrace();
       } catch (ClassNotFoundException e1) {
       e1.printStackTrace();
       }
       return null;
       }
       }

4. Then implement the jet.server.api.UserMailList interface, which gets the user and e-mail information from the customized data source. The following implementation gets the e-mail list from the Customers table, which contains Customer Name and Customer E-mail columns.

       import jet.server.api.*;
       import java.util.*;
       import java.sql.*;
       public class UserMailList_InvoiceReport_cls_Impl implements UserMailList {
       public static Hashtable userEmails = new Hashtable();
       private String curRealmName = "defaultRealm";
       public UserMailList_InvoiceReport_cls_Impl()
       {
       loadData();
       }
       private void loadData ()
       {
       try{
       String jdbcDriver = "sun.jdbc.odbc.JdbcOdbcDriver";
       DriverManager.registerDriver((Driver)Class.forName(jdbcDriver).newInstance());
       Connection conn = DriverManager.getConnection("jdbc:odbc:jinfonet4");
       Statement stmt = conn.createStatement();
       ResultSet rs = stmt.executeQuery("select * from Customers");
       String userName = null;
       String userEmail = null;
       while(rs.next()){
       userName = rs.getString("Customer Name");
       userEmail = rs.getString("Customer Email");
       if (userEmail != null) {
       userEmails.put(userName, userEmail);
       }
       }
       }catch(Exception e){
       e.printStackTrace();
       }
       }
       public java.util.Enumeration getAllMailAddresses(String realmName){
       if (realmName.equals(curRealmName)) {
       return userEmails.elements();
       }else{
       return null;
       }
       }
       public java.util.Enumeration getGroupMailAddresses
       (String realmName, String groupName) {
       if (realmName.equals(curRealmName) && userEmails.containsKey(groupName)) {
       Vector groupEmails = new Vector();
       groupEmails.addElement(userEmails.get(groupName));
       return groupEmails.elements() ;
       }else{
       return null;
       }
       }
       public java.util.Enumeration getRoleMailAddresses
       (String realmName, String roleName) {
       if (realmName.equals(curRealmName) && userEmails.containsKey(roleName)) {
       Vector roleEmails = new Vector();
       roleEmails.addElement(userEmails.get(roleName));
       return roleEmails.elements() ;
       }else{
       return null;
       }
       }
       public java.lang.String getMailAddress(String realmName, String userName) {
       if (realmName.equals(curRealmName) && userEmails.containsKey(userName)) {
       return (String)userEmails.get(userName);
       }else{
       return null;
       }
       }
       }

5. Register the above classes to JReport Enterprise Server before the server is started.
   1. Add the parameter -Dcom.jinfonet.mailListFactory=UserMailListFactoryImplName to the command line/batch file that starts JReport Enterprise Server, where UserMailListFactoryImplName indicates the implementation of the jet.server.api.UserMailListFactory interface.

      In this case, the parameter should be -Dcom.jinfonet.mailListFactory=DemoUserMailListFactoryImpl.

   2. Add the path of the implementation classes to the class path of the command line/batch file.
6. Start JReport Enterprise Server and then publish the report and catalog.
7. Schedule the report, publish to e-mail, check the option This report has Page Level Security. E-mail the report to each specified user. Provide the necessary information and then submit the schedule.

The report will be processed and sent to the corresponding recipients with pertinent report data.