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 * <mailet match="SMTPAuthSuccessful" class="WhiteListManager">
61 * <repositoryPath> db://maildb </repositoryPath>
62 * <!--
63 * If true automatically inserts the local sender to remote recipients entries in the whitelist (default is false).
64 * -->
65 * <automaticInsert>true</automaticInsert>
66 * <!--
67 * Set this to an email address of the "whitelist manager" to send commands to (default is null).
68 * -->
69 * <whitelistManagerAddress>whitelist.manager@xxx.yyy</whitelistManagerAddress>
70 * <!--
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 * -->
74 * <displayFlag>display whitelist</displayFlag>
75 * <!--
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 * -->
79 * <insertFlag>insert whitelist</insertFlag>
80 * <!--
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 * -->
84 * <removeFlag>remove whitelist</removeFlag>
85 * </mailet>
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
219 DataSourceSelector datasources = (DataSourceSelector) serviceManager.lookup(DataSourceSelector.ROLE);
220
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
693 MimeMessage reply = new MimeMessage(Session.getDefaultInstance(System.getProperties(), null));
694
695
696 InternetAddress[] rcptAddr = new InternetAddress[1];
697 rcptAddr[0] = senderMailAddress.toInternetAddress();
698 reply.setRecipients(Message.RecipientType.TO, rcptAddr);
699
700
701 reply.setFrom(notifier.toInternetAddress());
702
703
704 MimeMultipart multipart = new MimeMultipart();
705
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
715 Set recipients = new HashSet();
716 recipients.add(senderMailAddress);
717
718
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
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
783
784
785 boolean dbUpdated = false;
786
787 dbUpdated = createTable(conn, "whiteListTableName", "createWhiteListTable");
788
789
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
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