View Javadoc

1   /************************************************************************
2    * Copyright (c) 2000-2006 The Apache Software Foundation.             *
3    * All rights reserved.                                                *
4    * ------------------------------------------------------------------- *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you *
6    * may not use this file except in compliance with the License. You    *
7    * may obtain a copy of the License at:                                *
8    *                                                                     *
9    *     http://www.apache.org/licenses/LICENSE-2.0                      *
10   *                                                                     *
11   * Unless required by applicable law or agreed to in writing, software *
12   * distributed under the License is distributed on an "AS IS" BASIS,   *
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
14   * implied.  See the License for the specific language governing       *
15   * permissions and limitations under the License.                      *
16   ***********************************************************************/
17  
18  package org.apache.james.transport.mailets;
19  
20  import org.apache.mailet.*;
21  import org.apache.mailet.dates.RFC822DateFormat;
22  
23  import org.apache.avalon.cornerstone.services.datasources.*;
24  import org.apache.avalon.excalibur.datasource.*;
25  import org.apache.avalon.framework.service.*;
26  
27  import org.apache.james.*;
28  import org.apache.james.core.*;
29  import org.apache.james.services.*;
30  import org.apache.james.util.*;
31  
32  import javax.mail.*;
33  import javax.mail.internet.*;
34  
35  import java.sql.*;
36  import java.util.*;
37  import java.text.*;
38  import java.io.*;
39  
40  /*** <P>Manages for each local user a "white list" of remote addresses whose messages
41   * should never be blocked as spam.</P>
42   * <P>The normal behaviour is to check, for a local sender, if a remote recipient
43   * is already in the list: if not, it will be automatically inserted.
44   * This is under the interpretation that if a local sender <I>X</I> sends a message to a
45   * remote recipient <I>Y</I>, then later on if a message is sent by <I>Y</I> to <I>X</I> it should be
46   * considered always valid and never blocked; hence <I>Y</I> should be in the white list
47   * of <I>X</I>.</P>
48   * <P>Another mode of operations is when a local sender sends a message to <I>whitelistManagerAddress</I>
49   * with one of three specific values in the subject, to
50   * (i) send back a message displaying a list of the addresses in his own list;
51   * (ii) insert some new addresses in his own list;
52   * (iii) remove some addresses from his own list.
53   * In all this cases the message will be ghosted and the postmaster will reply
54   * to the sender.</P>
55   * <P> The sender name is always converted to its primary name (handling aliases).</P>
56   * <P>Sample configuration:</P>
57   * <PRE><CODE>
58   * &lt;mailet match="SMTPAuthSuccessful" class="WhiteListManager"&gt;
59   *   &lt;repositoryPath&gt; db://maildb &lt;/repositoryPath&gt;
60   *   &lt;!--
61   *     If true automatically inserts the local sender to remote recipients entries in the whitelist (default is false).
62   *   --&gt;
63   *   &lt;automaticInsert&gt;true&lt;/automaticInsert&gt;
64   *   &lt;!--
65   *     Set this to an email address of the "whitelist manager" to send commands to (default is null).
66   *   --&gt;
67   *   &lt;whitelistManagerAddress&gt;whitelist.manager@xxx.yyy&lt;/whitelistManagerAddress&gt;
68   *   &lt;!--
69   *     Set this to a unique text that you can use (by sending a message to the "whitelist manager" above)
70   *     to tell the mailet to send back the contents of the white list (default is null).
71   *   --&gt;
72   *   &lt;displayFlag&gt;display whitelist&lt;/displayFlag&gt;
73   *   &lt;!--
74   *     Set this to a unique text that you can use (by sending a message to the "whitelist manager" above)
75   *     to tell the mailet to insert some new remote recipients to the white list (default is null).
76   *   --&gt;
77   *   &lt;insertFlag&gt;insert whitelist&lt;/insertFlag&gt;
78   *   &lt;!--
79   *     Set this to a unique text that you can use (by sending a message to the "whitelist manager" above)
80   *     to tell the mailet to remove some remote recipients from the white list (default is null).
81   *   --&gt;
82   *   &lt;removeFlag&gt;remove whitelist&lt;/removeFlag&gt;
83   * &lt;/mailet&gt;
84   * </CODE></PRE>
85   *
86   * @see org.apache.james.transport.matchers.IsInWhiteList
87   * @version SVN $Revision: $ $Date: $
88   * @since 2.3.0
89   */
90  public class WhiteListManager extends GenericMailet {
91      
92      private boolean automaticInsert;
93      private String displayFlag;
94      private String insertFlag;
95      private String removeFlag;
96      private MailAddress whitelistManagerAddress;
97      
98      private String selectByPK;
99      private String selectBySender;
100     private String insert;
101     private String deleteByPK;
102     
103     /*** The date format object used to generate RFC 822 compliant date headers. */
104     private RFC822DateFormat rfc822DateFormat = new RFC822DateFormat();
105 
106     private DataSourceComponent datasource;
107     
108    /*** The store containing the local user repository. */
109     private UsersStore usersStore;
110 
111     /*** The user repository for this mail server.  Contains all the users with inboxes
112      * on this server.
113      */
114     private UsersRepository localusers;
115 
116     /***
117      * The JDBCUtil helper class
118      */
119     private final JDBCUtil theJDBCUtil = new JDBCUtil() {
120         protected void delegatedLog(String logString) {
121             log("WhiteListManager: " + logString);
122         }
123     };
124     
125     /***
126      * Contains all of the sql strings for this component.
127      */
128     private SqlResources sqlQueries = new SqlResources();
129 
130     /***
131      * Holds value of property sqlFile.
132      */
133     private File sqlFile;
134 
135      /***
136      * Holds value of property sqlParameters.
137      */
138     private Map sqlParameters = new HashMap();
139 
140     /***
141      * Getter for property sqlParameters.
142      * @return Value of property sqlParameters.
143      */
144     private Map getSqlParameters() {
145 
146         return this.sqlParameters;
147     }
148 
149     /***
150      * Setter for property sqlParameters.
151      * @param sqlParameters New value of property sqlParameters.
152      */
153     private void setSqlParameters(Map sqlParameters) {
154 
155         this.sqlParameters = sqlParameters;
156     }
157 
158     /*** Initializes the mailet.
159      */
160     public void init() throws MessagingException {
161         automaticInsert = new Boolean(getInitParameter("automaticInsert")).booleanValue();
162         log("automaticInsert: " + automaticInsert);
163 
164         displayFlag = getInitParameter("displayFlag");
165         insertFlag = getInitParameter("insertFlag");
166         removeFlag = getInitParameter("removeFlag");
167         
168         String whitelistManagerAddressString = getInitParameter("whitelistManagerAddress");
169         if (whitelistManagerAddressString != null) {
170             whitelistManagerAddressString = whitelistManagerAddressString.trim();
171             log("whitelistManagerAddress: " + whitelistManagerAddressString);
172             try {
173                 whitelistManagerAddress = new MailAddress(whitelistManagerAddressString);
174             }
175             catch (javax.mail.internet.ParseException pe) {
176                 throw new MessagingException("Bad whitelistManagerAddress", pe);
177             }
178             
179             if (displayFlag != null) {
180                 displayFlag = displayFlag.trim();
181                 log("displayFlag: " + displayFlag);
182             }
183             else {
184                 log("displayFlag is null");
185             }
186             if (insertFlag != null) {
187                 insertFlag = insertFlag.trim();
188                 log("insertFlag: " + insertFlag);
189             }
190             else {
191                 log("insertFlag is null");
192             }
193             if (removeFlag != null) {
194                 removeFlag = removeFlag.trim();
195                 log("removeFlag: " + removeFlag);
196             }
197             else {
198                 log("removeFlag is null");
199             }
200         }
201         else {
202             log("whitelistManagerAddress is null; will ignore commands");
203         }
204         
205         String repositoryPath = getInitParameter("repositoryPath");
206         if (repositoryPath != null) {
207             log("repositoryPath: " + repositoryPath);
208         }
209         else {
210             throw new MessagingException("repositoryPath is null");
211         }
212 
213         ServiceManager serviceManager = (ServiceManager) getMailetContext().getAttribute(Constants.AVALON_COMPONENT_MANAGER);
214 
215         try {
216             // Get the DataSourceSelector block
217             DataSourceSelector datasources = (DataSourceSelector) serviceManager.lookup(DataSourceSelector.ROLE);
218             // Get the data-source required.
219             int stindex =   repositoryPath.indexOf("://") + 3;
220             String datasourceName = repositoryPath.substring(stindex);
221             datasource = (DataSourceComponent) datasources.select(datasourceName);
222         } catch (Exception e) {
223             throw new MessagingException("Can't get datasource", e);
224         }
225 
226          try {
227             // Get the UsersRepository
228             usersStore = (UsersStore)serviceManager.lookup(UsersStore.ROLE);
229             localusers = (UsersRepository)usersStore.getRepository("LocalUsers");
230         } catch (Exception e) {
231             throw new MessagingException("Can't get the local users repository", e);
232         }
233 
234         try {
235             initSqlQueries(datasource.getConnection(), getMailetContext());
236         } catch (Exception e) {
237             throw new MessagingException("Exception initializing queries", e);
238         }        
239         
240         selectByPK = sqlQueries.getSqlString("selectByPK", true);
241         selectBySender = sqlQueries.getSqlString("selectBySender", true);
242         insert = sqlQueries.getSqlString("insert", true);
243         deleteByPK = sqlQueries.getSqlString("deleteByPK", true);
244     }
245     
246     /*** Services the mailet.
247      */    
248     public void service(Mail mail) throws MessagingException {
249         
250         // check if it's a local sender
251         MailAddress senderMailAddress = mail.getSender();
252         if (senderMailAddress == null) {
253             return;
254         }
255         String senderUser = senderMailAddress.getUser();
256         String senderHost = senderMailAddress.getHost();
257         if (   !getMailetContext().isLocalServer(senderHost)
258             || !getMailetContext().isLocalUser(senderUser)) {
259             // not a local sender, so return
260             return;
261         }
262         
263         Collection recipients = mail.getRecipients();
264         
265         if (recipients.size() == 1
266         && whitelistManagerAddress != null
267         && whitelistManagerAddress.equals(recipients.toArray()[0])) {
268             
269             mail.setState(Mail.GHOST);
270         
271             String subject = mail.getMessage().getSubject();
272             if (displayFlag != null && displayFlag.equals(subject)) {
273                 manageDisplayRequest(mail);
274             }
275             else if (insertFlag != null && insertFlag.equals(subject)) {
276                 manageInsertRequest(mail);
277             }
278             else if (removeFlag != null && removeFlag.equals(subject)) {
279                 manageRemoveRequest(mail);
280             }
281             else {
282                 StringWriter sout = new StringWriter();
283                 PrintWriter out = new PrintWriter(sout, true);
284                 out.println("Answering on behalf of: " + whitelistManagerAddress);
285                 out.println("ERROR: Unknown command in the subject line: " + subject);
286                 sendReplyFromPostmaster(mail, sout.toString());
287             }
288             return;
289         }
290         
291         if (automaticInsert) {
292             checkAndInsert(senderMailAddress, recipients);
293         }
294         
295     }
296     
297     /*** Returns a string describing this mailet.
298      *
299      * @return a string describing this mailet
300      */
301     public String getMailetInfo() {
302         return "White List Manager mailet";
303     }
304     
305     /*** Loops through each address in the recipient list, checks if in the senders
306      * list and inserts in it otherwise.
307      */    
308     private void checkAndInsert(MailAddress senderMailAddress, Collection recipients) throws MessagingException {
309         String senderUser = senderMailAddress.getUser().toLowerCase(Locale.US);
310         String senderHost = senderMailAddress.getHost().toLowerCase(Locale.US);
311         
312         senderUser = getPrimaryName(senderUser);
313         
314         Connection conn = null;
315         PreparedStatement selectStmt = null;
316         PreparedStatement insertStmt = null;
317         boolean dbUpdated = false;
318         
319         try {
320             
321             for (Iterator i = recipients.iterator(); i.hasNext(); ) {
322                 ResultSet selectRS = null;
323                 try {
324                     MailAddress recipientMailAddress = (MailAddress)i.next();
325                     String recipientUser = recipientMailAddress.getUser().toLowerCase(Locale.US);
326                     String recipientHost = recipientMailAddress.getHost().toLowerCase(Locale.US);
327                     
328                     if (getMailetContext().isLocalServer(recipientHost)) {
329                         // not a remote recipient, so skip
330                         continue;
331                     }
332                     
333                     if (conn == null) {
334                         conn = datasource.getConnection();
335                     }
336                     
337                     if (selectStmt == null) {
338                         selectStmt = conn.prepareStatement(selectByPK);
339                     }
340                     selectStmt.setString(1, senderUser);
341                     selectStmt.setString(2, senderHost);
342                     selectStmt.setString(3, recipientUser);
343                     selectStmt.setString(4, recipientHost);
344                     selectRS = selectStmt.executeQuery();
345                     if (selectRS.next()) {
346                         //This address was already in the list
347                         continue;
348                     }
349                     
350                     if (insertStmt == null) {
351                         insertStmt = conn.prepareStatement(insert);
352                     }
353                     insertStmt.setString(1, senderUser);
354                     insertStmt.setString(2, senderHost);
355                     insertStmt.setString(3, recipientUser);
356                     insertStmt.setString(4, recipientHost);
357                     insertStmt.executeUpdate();
358                     dbUpdated = true;
359                     
360                 } finally {
361                     theJDBCUtil.closeJDBCResultSet(selectRS);
362                 }
363                 
364                 //Commit our changes if necessary.
365                 if (conn != null && dbUpdated && !conn.getAutoCommit()) {
366                     conn.commit();
367                     dbUpdated = false;
368                 }
369             }
370         } catch (SQLException sqle) {
371             log("Error accessing database", sqle);
372             throw new MessagingException("Exception thrown", sqle);
373         } finally {
374             theJDBCUtil.closeJDBCStatement(selectStmt);
375             theJDBCUtil.closeJDBCStatement(insertStmt);
376             //Rollback our changes if necessary.
377             try {
378                 if (conn != null && dbUpdated && !conn.getAutoCommit()) {
379                     conn.rollback();
380                     dbUpdated = false;
381                 }
382             }
383             catch (Exception e) {}
384             theJDBCUtil.closeJDBCConnection(conn);
385         }
386     }
387     
388     /*** Manages a display request.
389      */    
390     private void manageDisplayRequest(Mail mail)
391     throws MessagingException {
392         MailAddress senderMailAddress = mail.getSender();
393         String senderUser = senderMailAddress.getUser().toLowerCase(Locale.US);
394         String senderHost = senderMailAddress.getHost().toLowerCase(Locale.US);
395         
396         senderUser = getPrimaryName(senderUser);
397         
398         Connection conn = null;
399         PreparedStatement selectStmt = null;
400         ResultSet selectRS = null;
401         
402         StringWriter sout = new StringWriter();
403         PrintWriter out = new PrintWriter(sout, true);
404         
405         try {
406             out.println("Answering on behalf of: " + whitelistManagerAddress);
407             out.println("Displaying white list of " + (new MailAddress(senderUser, senderHost)) + ":");
408             out.println();
409             
410             conn = datasource.getConnection();
411             selectStmt = conn.prepareStatement(selectBySender);
412             selectStmt.setString(1, senderUser);
413             selectStmt.setString(2, senderHost);
414             selectRS = selectStmt.executeQuery();
415             while (selectRS.next()) {
416                 MailAddress mailAddress =
417                     new MailAddress(selectRS.getString(1), selectRS.getString(2));
418                 out.println(mailAddress.toInternetAddress().toString());
419             }
420             
421             out.println();
422             out.println("Finished");
423             
424             sendReplyFromPostmaster(mail, sout.toString());
425                         
426         } catch (SQLException sqle) {
427             out.println("Error accessing the database");
428             sendReplyFromPostmaster(mail, sout.toString());
429             throw new MessagingException("Error accessing database", sqle);
430         } finally {
431             theJDBCUtil.closeJDBCResultSet(selectRS);
432             theJDBCUtil.closeJDBCStatement(selectStmt);
433             theJDBCUtil.closeJDBCConnection(conn);
434         }
435     }
436     
437     /*** Manages an insert request.
438      */    
439     private void manageInsertRequest(Mail mail)
440     throws MessagingException {
441         MailAddress senderMailAddress = mail.getSender();
442         String senderUser = senderMailAddress.getUser().toLowerCase(Locale.US);
443         String senderHost = senderMailAddress.getHost().toLowerCase(Locale.US);
444         
445         senderUser = getPrimaryName(senderUser);
446         
447         Connection conn = null;
448         PreparedStatement selectStmt = null;
449         PreparedStatement insertStmt = null;
450         boolean dbUpdated = false;
451         
452         StringWriter sout = new StringWriter();
453         PrintWriter out = new PrintWriter(sout, true);
454         
455         try {
456             out.println("Answering on behalf of: " + whitelistManagerAddress);
457             out.println("Inserting in the white list of " + (new MailAddress(senderUser, senderHost)) + " ...");
458             out.println();
459             
460             MimeMessage message = mail.getMessage() ;
461             
462             Object content= message.getContent();
463             
464             if (message.getContentType().startsWith("text/plain")
465             && content instanceof String) {
466                 StringTokenizer st = new StringTokenizer((String) content, " \t\n\r\f,;:<>");
467                 while (st.hasMoreTokens()) {
468                     ResultSet selectRS = null;
469                     try {
470                         MailAddress recipientMailAddress;
471                         try {
472                             recipientMailAddress = new MailAddress(st.nextToken());
473                         }
474                         catch (javax.mail.internet.ParseException pe) {
475                             continue;
476                         }
477                         String recipientUser = recipientMailAddress.getUser().toLowerCase(Locale.US);
478                         String recipientHost = recipientMailAddress.getHost().toLowerCase(Locale.US);
479                         
480                         if (getMailetContext().isLocalServer(recipientHost)) {
481                             // not a remote recipient, so skip
482                             continue;
483                         }
484                         
485                         if (conn == null) {
486                             conn = datasource.getConnection();
487                         }
488                         
489                         if (selectStmt == null) {
490                             selectStmt = conn.prepareStatement(selectByPK);
491                         }
492                         selectStmt.setString(1, senderUser);
493                         selectStmt.setString(2, senderHost);
494                         selectStmt.setString(3, recipientUser);
495                         selectStmt.setString(4, recipientHost);
496                         selectRS = selectStmt.executeQuery();
497                         if (selectRS.next()) {
498                             //This address was already in the list
499                             out.println("Skipped:  " + recipientMailAddress);
500                             continue;
501                         }
502                         
503                         if (insertStmt == null) {
504                             insertStmt = conn.prepareStatement(insert);
505                         }
506                         insertStmt.setString(1, senderUser);
507                         insertStmt.setString(2, senderHost);
508                         insertStmt.setString(3, recipientUser);
509                         insertStmt.setString(4, recipientHost);
510                         insertStmt.executeUpdate();
511                         dbUpdated = true;
512                         out.println("Inserted: " + recipientMailAddress);
513                         
514                     } finally {
515                         theJDBCUtil.closeJDBCResultSet(selectRS);
516                     }
517                 }
518                 
519                 if (dbUpdated) {
520                     log("Insertion request issued by " + senderMailAddress);
521                 }
522                 //Commit our changes if necessary.
523                 if (conn != null && dbUpdated && !conn.getAutoCommit()) {
524                     conn.commit() ;
525                     dbUpdated = false;
526                 }
527             }
528             else {
529                 out.println("The message must be plain - no action");
530             }
531             
532             out.println();
533             out.println("Finished");
534             
535             sendReplyFromPostmaster(mail, sout.toString());
536             
537         } catch (SQLException sqle) {
538             out.println("Error accessing the database");
539             sendReplyFromPostmaster(mail, sout.toString());
540             throw new MessagingException("Error accessing the database", sqle);
541         } catch (IOException ioe) {
542             out.println("Error getting message content");
543             sendReplyFromPostmaster(mail, sout.toString());
544             throw new MessagingException("Error getting message content", ioe);
545         } finally {
546             theJDBCUtil.closeJDBCStatement(selectStmt);
547             theJDBCUtil.closeJDBCStatement(insertStmt);
548             //Rollback our changes if necessary.
549             try {
550                 if (conn != null && dbUpdated && !conn.getAutoCommit()) {
551                     conn.rollback() ;
552                     dbUpdated = false;
553                 }
554             }
555             catch (Exception e) {}
556             theJDBCUtil.closeJDBCConnection(conn);
557         }
558     }
559     
560     /*** Manages a remove request.
561      */    
562     private void manageRemoveRequest(Mail mail)
563     throws MessagingException {
564         MailAddress senderMailAddress = mail.getSender();
565         String senderUser = senderMailAddress.getUser().toLowerCase(Locale.US);
566         String senderHost = senderMailAddress.getHost().toLowerCase(Locale.US);
567         
568         senderUser = getPrimaryName(senderUser);
569         
570         Connection conn = null;
571         PreparedStatement selectStmt = null;
572         PreparedStatement deleteStmt = null;
573         boolean dbUpdated = false;
574         
575         StringWriter sout = new StringWriter();
576         PrintWriter out = new PrintWriter(sout, true);
577         
578         try {
579             out.println("Answering on behalf of: " + whitelistManagerAddress);
580             out.println("Removing from the white list of " + (new MailAddress(senderUser, senderHost)) + " ...");
581             out.println();
582             
583             MimeMessage message = mail.getMessage() ;
584             
585             Object content= message.getContent();
586             
587             if (message.getContentType().startsWith("text/plain")
588             && content instanceof String) {
589                 StringTokenizer st = new StringTokenizer((String) content, " \t\n\r\f,;:<>");
590                 while (st.hasMoreTokens()) {
591                     ResultSet selectRS = null;
592                     try {
593                         MailAddress recipientMailAddress;
594                         try {
595                             recipientMailAddress = new MailAddress(st.nextToken());
596                         }
597                         catch (javax.mail.internet.ParseException pe) {
598                             continue;
599                         }
600                         String recipientUser = recipientMailAddress.getUser().toLowerCase(Locale.US);
601                         String recipientHost = recipientMailAddress.getHost().toLowerCase(Locale.US);
602                         
603                         if (getMailetContext().isLocalServer(recipientHost)) {
604                             // not a remote recipient, so skip
605                             continue;
606                         }
607                         
608                         if (conn == null) {
609                             conn = datasource.getConnection();
610                         }
611                         
612                         if (selectStmt == null) {
613                             selectStmt = conn.prepareStatement(selectByPK);
614                         }
615                         selectStmt.setString(1, senderUser);
616                         selectStmt.setString(2, senderHost);
617                         selectStmt.setString(3, recipientUser);
618                         selectStmt.setString(4, recipientHost);
619                         selectRS = selectStmt.executeQuery();
620                         if (!selectRS.next()) {
621                             //This address was not in the list
622                             out.println("Skipped: " + recipientMailAddress);
623                             continue;
624                         }
625                         
626                         if (deleteStmt == null) {
627                             deleteStmt = conn.prepareStatement(deleteByPK);
628                         }
629                         deleteStmt.setString(1, senderUser);
630                         deleteStmt.setString(2, senderHost);
631                         deleteStmt.setString(3, recipientUser);
632                         deleteStmt.setString(4, recipientHost);
633                         deleteStmt.executeUpdate();
634                         dbUpdated = true;
635                         out.println("Removed: " + recipientMailAddress);
636                         
637                     } finally {
638                         theJDBCUtil.closeJDBCResultSet(selectRS);
639                     }
640                 }
641 
642                 if (dbUpdated) {
643                     log("Removal request issued by " + senderMailAddress);
644                 }
645                 //Commit our changes if necessary.
646                 if (conn != null && dbUpdated && !conn.getAutoCommit()) {
647                     conn.commit() ;
648                     dbUpdated = false;
649                 }
650             }
651             else {
652                 out.println("The message must be plain - no action");
653             }
654             
655             out.println();
656             out.println("Finished");
657             
658             sendReplyFromPostmaster(mail, sout.toString());
659             
660         } catch (SQLException sqle) {
661             out.println("Error accessing the database");
662             sendReplyFromPostmaster(mail, sout.toString());
663             throw new MessagingException("Error accessing the database", sqle);
664         } catch (IOException ioe) {
665             out.println("Error getting message content");
666             sendReplyFromPostmaster(mail, sout.toString());
667             throw new MessagingException("Error getting message content", ioe);
668         } finally {
669             theJDBCUtil.closeJDBCStatement(selectStmt);
670             theJDBCUtil.closeJDBCStatement(deleteStmt);
671             //Rollback our changes if necessary.
672             try {
673                 if (conn != null && dbUpdated && !conn.getAutoCommit()) {
674                     conn.rollback() ;
675                     dbUpdated = false;
676                 }
677             }
678             catch (Exception e) {}
679             theJDBCUtil.closeJDBCConnection(conn);
680         }
681     }
682     
683     private void sendReplyFromPostmaster(Mail mail, String stringContent) throws MessagingException {
684         try {
685             MailAddress notifier = getMailetContext().getPostmaster();
686             
687             MailAddress senderMailAddress = mail.getSender();
688             
689             MimeMessage message = mail.getMessage();
690             //Create the reply message
691             MimeMessage reply = new MimeMessage(Session.getDefaultInstance(System.getProperties(), null));
692             
693             //Create the list of recipients in the Address[] format
694             InternetAddress[] rcptAddr = new InternetAddress[1];
695             rcptAddr[0] = senderMailAddress.toInternetAddress();
696             reply.setRecipients(Message.RecipientType.TO, rcptAddr);
697             
698             //Set the sender...
699             reply.setFrom(notifier.toInternetAddress());
700             
701             //Create the message body
702             MimeMultipart multipart = new MimeMultipart();
703             //Add message as the first mime body part
704             MimeBodyPart part = new MimeBodyPart();
705             part.setContent(stringContent, "text/plain");
706             part.setHeader(RFC2822Headers.CONTENT_TYPE, "text/plain");
707             multipart.addBodyPart(part);
708             
709             reply.setContent(multipart);
710             reply.setHeader(RFC2822Headers.CONTENT_TYPE, multipart.getContentType());
711             
712             //Create the list of recipients in our MailAddress format
713             Set recipients = new HashSet();
714             recipients.add(senderMailAddress);
715             
716             //Set additional headers
717             if (reply.getHeader(RFC2822Headers.DATE)==null){
718                 reply.setHeader(RFC2822Headers.DATE, rfc822DateFormat.format(new java.util.Date()));
719             }
720             String subject = message.getSubject();
721             if (subject == null) {
722                 subject = "";
723             }
724             if (subject.indexOf("Re:") == 0){
725                 reply.setSubject(subject);
726             } else {
727                 reply.setSubject("Re:" + subject);
728             }
729             reply.setHeader(RFC2822Headers.IN_REPLY_TO, message.getMessageID());
730             
731             //Send it off...
732             getMailetContext().sendMail(notifier, recipients, reply);
733         }
734         catch (Exception e) {
735             log("Exception found sending reply", e);
736         }
737     }
738     
739     /*** Gets the main name of a local customer, handling alias */
740     private String getPrimaryName(String originalUsername) {
741         String username;
742         try {
743             username = localusers.getRealName(originalUsername);
744             JamesUser user = (JamesUser) localusers.getUserByName(username);
745             if (user.getAliasing()) {
746                 username = user.getAlias();
747             }
748         }
749         catch (Exception e) {
750             username = originalUsername;
751         }
752         return username;
753     }
754     
755     /***
756      * Initializes the sql query environment from the SqlResources file.
757      * Will look for conf/sqlResources.xml.
758      * @param conn The connection for accessing the database
759      * @param mailetContext The current mailet context,
760      * for finding the conf/sqlResources.xml file
761      * @throws Exception If any error occurs
762      */
763     public void initSqlQueries(Connection conn, org.apache.mailet.MailetContext mailetContext) throws Exception {
764         try {
765             if (conn.getAutoCommit()) {
766                 conn.setAutoCommit(false);
767             }
768             
769             this.sqlFile = new File((String) mailetContext.getAttribute("confDir"), "sqlResources.xml").getCanonicalFile();
770             sqlQueries.init(this.sqlFile, "WhiteList" , conn, getSqlParameters());
771             
772             checkTables(conn);
773         } finally {
774             theJDBCUtil.closeJDBCConnection(conn);
775         }
776     }
777     
778     private void checkTables(Connection conn) throws SQLException {
779         DatabaseMetaData dbMetaData = conn.getMetaData();
780         // Need to ask in the case that identifiers are stored, ask the DatabaseMetaInfo.
781         // Try UPPER, lower, and MixedCase, to see if the table is there.
782         
783         boolean dbUpdated = false;
784         
785         dbUpdated = createTable(conn, "whiteListTableName", "createWhiteListTable");
786         
787         //Commit our changes if necessary.
788         if (conn != null && dbUpdated && !conn.getAutoCommit()) {
789             conn.commit();
790             dbUpdated = false;
791         }
792             
793     }
794     
795     private boolean createTable(Connection conn, String tableNameSqlStringName, String createSqlStringName) throws SQLException {
796         String tableName = sqlQueries.getSqlString(tableNameSqlStringName, true);
797         
798         DatabaseMetaData dbMetaData = conn.getMetaData();
799 
800         // Try UPPER, lower, and MixedCase, to see if the table is there.
801         if (theJDBCUtil.tableExists(dbMetaData, tableName)) {
802             return false;
803         }
804         
805         PreparedStatement createStatement = null;
806         
807         try {
808             createStatement =
809                     conn.prepareStatement(sqlQueries.getSqlString(createSqlStringName, true));
810             createStatement.execute();
811             
812             StringBuffer logBuffer = null;
813             logBuffer =
814                     new StringBuffer(64)
815                     .append("Created table '")
816                     .append(tableName)
817                     .append("' using sqlResources string '")
818                     .append(createSqlStringName)
819                     .append("'.");
820             log(logBuffer.toString());
821             
822         } finally {
823             theJDBCUtil.closeJDBCStatement(createStatement);
824         }
825         
826         return true;
827     }
828     
829 }
830