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 * <mailet match="SMTPAuthSuccessful" class="WhiteListManager">
59 * <repositoryPath> db://maildb </repositoryPath>
60 * <!--
61 * If true automatically inserts the local sender to remote recipients entries in the whitelist (default is false).
62 * -->
63 * <automaticInsert>true</automaticInsert>
64 * <!--
65 * Set this to an email address of the "whitelist manager" to send commands to (default is null).
66 * -->
67 * <whitelistManagerAddress>whitelist.manager@xxx.yyy</whitelistManagerAddress>
68 * <!--
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 * -->
72 * <displayFlag>display whitelist</displayFlag>
73 * <!--
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 * -->
77 * <insertFlag>insert whitelist</insertFlag>
78 * <!--
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 * -->
82 * <removeFlag>remove whitelist</removeFlag>
83 * </mailet>
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
217 DataSourceSelector datasources = (DataSourceSelector) serviceManager.lookup(DataSourceSelector.ROLE);
218
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
691 MimeMessage reply = new MimeMessage(Session.getDefaultInstance(System.getProperties(), null));
692
693
694 InternetAddress[] rcptAddr = new InternetAddress[1];
695 rcptAddr[0] = senderMailAddress.toInternetAddress();
696 reply.setRecipients(Message.RecipientType.TO, rcptAddr);
697
698
699 reply.setFrom(notifier.toInternetAddress());
700
701
702 MimeMultipart multipart = new MimeMultipart();
703
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
713 Set recipients = new HashSet();
714 recipients.add(senderMailAddress);
715
716
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
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
781
782
783 boolean dbUpdated = false;
784
785 dbUpdated = createTable(conn, "whiteListTableName", "createWhiteListTable");
786
787
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
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