View Javadoc

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