001: /****************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one *
003: * or more contributor license agreements. See the NOTICE file *
004: * distributed with this work for additional information *
005: * regarding copyright ownership. The ASF licenses this file *
006: * to you under the Apache License, Version 2.0 (the *
007: * "License"); you may not use this file except in compliance *
008: * with the License. You may obtain a copy of the License at *
009: * *
010: * http://www.apache.org/licenses/LICENSE-2.0 *
011: * *
012: * Unless required by applicable law or agreed to in writing, *
013: * software distributed under the License is distributed on an *
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015: * KIND, either express or implied. See the License for the *
016: * specific language governing permissions and limitations *
017: * under the License. *
018: ****************************************************************/package org.apache.james.transport.mailets;
019:
020: import org.apache.mailet.*;
021: import org.apache.mailet.dates.RFC822DateFormat;
022:
023: import org.apache.avalon.cornerstone.services.datasources.*;
024: import org.apache.avalon.excalibur.datasource.*;
025: import org.apache.avalon.framework.service.*;
026:
027: import org.apache.james.*;
028: import org.apache.james.core.*;
029: import org.apache.james.services.*;
030: import org.apache.james.util.*;
031:
032: import javax.mail.*;
033: import javax.mail.internet.*;
034:
035: import java.sql.*;
036: import java.util.*;
037: import java.text.*;
038: import java.io.*;
039:
040: /** <P>Manages for each local user a "white list" of remote addresses whose messages
041: * should never be blocked as spam.</P>
042: * <P>The normal behaviour is to check, for a local sender, if a remote recipient
043: * is already in the list: if not, it will be automatically inserted.
044: * This is under the interpretation that if a local sender <I>X</I> sends a message to a
045: * remote recipient <I>Y</I>, then later on if a message is sent by <I>Y</I> to <I>X</I> it should be
046: * considered always valid and never blocked; hence <I>Y</I> should be in the white list
047: * of <I>X</I>.</P>
048: * <P>Another mode of operations is when a local sender sends a message to <I>whitelistManagerAddress</I>
049: * with one of three specific values in the subject, to
050: * (i) send back a message displaying a list of the addresses in his own list;
051: * (ii) insert some new addresses in his own list;
052: * (iii) remove some addresses from his own list.
053: * In all this cases the message will be ghosted and the postmaster will reply
054: * to the sender.</P>
055: * <P> The sender name is always converted to its primary name (handling aliases).</P>
056: * <P>Sample configuration:</P>
057: * <PRE><CODE>
058: * <mailet match="SMTPAuthSuccessful" class="WhiteListManager">
059: * <repositoryPath> db://maildb </repositoryPath>
060: * <!--
061: * If true automatically inserts the local sender to remote recipients entries in the whitelist (default is false).
062: * -->
063: * <automaticInsert>true</automaticInsert>
064: * <!--
065: * Set this to an email address of the "whitelist manager" to send commands to (default is null).
066: * -->
067: * <whitelistManagerAddress>whitelist.manager@xxx.yyy</whitelistManagerAddress>
068: * <!--
069: * Set this to a unique text that you can use (by sending a message to the "whitelist manager" above)
070: * to tell the mailet to send back the contents of the white list (default is null).
071: * -->
072: * <displayFlag>display whitelist</displayFlag>
073: * <!--
074: * Set this to a unique text that you can use (by sending a message to the "whitelist manager" above)
075: * to tell the mailet to insert some new remote recipients to the white list (default is null).
076: * -->
077: * <insertFlag>insert whitelist</insertFlag>
078: * <!--
079: * Set this to a unique text that you can use (by sending a message to the "whitelist manager" above)
080: * to tell the mailet to remove some remote recipients from the white list (default is null).
081: * -->
082: * <removeFlag>remove whitelist</removeFlag>
083: * </mailet>
084: * </CODE></PRE>
085: *
086: * @see org.apache.james.transport.matchers.IsInWhiteList
087: * @version SVN $Revision: $ $Date: $
088: * @since 2.3.0
089: */
090: public class WhiteListManager extends GenericMailet {
091:
092: private boolean automaticInsert;
093: private String displayFlag;
094: private String insertFlag;
095: private String removeFlag;
096: private MailAddress whitelistManagerAddress;
097:
098: private String selectByPK;
099: 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(
162: getInitParameter("automaticInsert")).booleanValue();
163: log("automaticInsert: " + automaticInsert);
164:
165: displayFlag = getInitParameter("displayFlag");
166: insertFlag = getInitParameter("insertFlag");
167: removeFlag = getInitParameter("removeFlag");
168:
169: String whitelistManagerAddressString = getInitParameter("whitelistManagerAddress");
170: if (whitelistManagerAddressString != null) {
171: whitelistManagerAddressString = whitelistManagerAddressString
172: .trim();
173: log("whitelistManagerAddress: "
174: + whitelistManagerAddressString);
175: try {
176: whitelistManagerAddress = new MailAddress(
177: whitelistManagerAddressString);
178: } catch (javax.mail.internet.ParseException pe) {
179: throw new MessagingException(
180: "Bad whitelistManagerAddress", pe);
181: }
182:
183: if (displayFlag != null) {
184: displayFlag = displayFlag.trim();
185: log("displayFlag: " + displayFlag);
186: } else {
187: log("displayFlag is null");
188: }
189: if (insertFlag != null) {
190: insertFlag = insertFlag.trim();
191: log("insertFlag: " + insertFlag);
192: } else {
193: log("insertFlag is null");
194: }
195: if (removeFlag != null) {
196: removeFlag = removeFlag.trim();
197: log("removeFlag: " + removeFlag);
198: } else {
199: log("removeFlag is null");
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: } else {
209: throw new MessagingException("repositoryPath is null");
210: }
211:
212: ServiceManager serviceManager = (ServiceManager) getMailetContext()
213: .getAttribute(Constants.AVALON_COMPONENT_MANAGER);
214:
215: try {
216: // Get the DataSourceSelector block
217: DataSourceSelector datasources = (DataSourceSelector) serviceManager
218: .lookup(DataSourceSelector.ROLE);
219: // Get the data-source required.
220: int stindex = repositoryPath.indexOf("://") + 3;
221: String datasourceName = repositoryPath.substring(stindex);
222: datasource = (DataSourceComponent) datasources
223: .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
231: .lookup(UsersStore.ROLE);
232: localusers = (UsersRepository) usersStore
233: .getRepository("LocalUsers");
234: } catch (Exception e) {
235: throw new MessagingException(
236: "Can't get the local users repository", e);
237: }
238:
239: try {
240: initSqlQueries(datasource.getConnection(),
241: getMailetContext());
242: } catch (Exception e) {
243: throw new MessagingException(
244: "Exception initializing queries", e);
245: }
246:
247: selectByPK = sqlQueries.getSqlString("selectByPK", true);
248: selectBySender = sqlQueries
249: .getSqlString("selectBySender", true);
250: insert = sqlQueries.getSqlString("insert", true);
251: deleteByPK = sqlQueries.getSqlString("deleteByPK", true);
252: }
253:
254: /** Services the mailet.
255: */
256: public void service(Mail mail) throws MessagingException {
257:
258: // check if it's a local sender
259: MailAddress senderMailAddress = mail.getSender();
260: if (senderMailAddress == null) {
261: return;
262: }
263: String senderUser = senderMailAddress.getUser();
264: String senderHost = senderMailAddress.getHost();
265: if (!getMailetContext().isLocalServer(senderHost)
266: || !getMailetContext().isLocalUser(senderUser)) {
267: // not a local sender, so return
268: return;
269: }
270:
271: Collection recipients = mail.getRecipients();
272:
273: if (recipients.size() == 1
274: && whitelistManagerAddress != null
275: && whitelistManagerAddress
276: .equals(recipients.toArray()[0])) {
277:
278: mail.setState(Mail.GHOST);
279:
280: String subject = mail.getMessage().getSubject();
281: if (displayFlag != null && displayFlag.equals(subject)) {
282: manageDisplayRequest(mail);
283: } else if (insertFlag != null && insertFlag.equals(subject)) {
284: manageInsertRequest(mail);
285: } else if (removeFlag != null && removeFlag.equals(subject)) {
286: manageRemoveRequest(mail);
287: } else {
288: StringWriter sout = new StringWriter();
289: PrintWriter out = new PrintWriter(sout, true);
290: out.println("Answering on behalf of: "
291: + whitelistManagerAddress);
292: out
293: .println("ERROR: Unknown command in the subject line: "
294: + subject);
295: sendReplyFromPostmaster(mail, sout.toString());
296: }
297: return;
298: }
299:
300: if (automaticInsert) {
301: checkAndInsert(senderMailAddress, recipients);
302: }
303:
304: }
305:
306: /** Returns a string describing this mailet.
307: *
308: * @return a string describing this mailet
309: */
310: public String getMailetInfo() {
311: return "White List Manager mailet";
312: }
313:
314: /** Loops through each address in the recipient list, checks if in the senders
315: * list and inserts in it otherwise.
316: */
317: private void checkAndInsert(MailAddress senderMailAddress,
318: Collection recipients) throws MessagingException {
319: String senderUser = senderMailAddress.getUser().toLowerCase(
320: Locale.US);
321: String senderHost = senderMailAddress.getHost().toLowerCase(
322: Locale.US);
323:
324: senderUser = getPrimaryName(senderUser);
325:
326: Connection conn = null;
327: PreparedStatement selectStmt = null;
328: PreparedStatement insertStmt = null;
329: boolean dbUpdated = false;
330:
331: try {
332:
333: for (Iterator i = recipients.iterator(); i.hasNext();) {
334: ResultSet selectRS = null;
335: try {
336: MailAddress recipientMailAddress = (MailAddress) i
337: .next();
338: String recipientUser = recipientMailAddress
339: .getUser().toLowerCase(Locale.US);
340: String recipientHost = recipientMailAddress
341: .getHost().toLowerCase(Locale.US);
342:
343: if (getMailetContext().isLocalServer(recipientHost)) {
344: // not a remote recipient, so skip
345: continue;
346: }
347:
348: if (conn == null) {
349: conn = datasource.getConnection();
350: }
351:
352: if (selectStmt == null) {
353: selectStmt = conn.prepareStatement(selectByPK);
354: }
355: selectStmt.setString(1, senderUser);
356: selectStmt.setString(2, senderHost);
357: selectStmt.setString(3, recipientUser);
358: selectStmt.setString(4, recipientHost);
359: selectRS = selectStmt.executeQuery();
360: if (selectRS.next()) {
361: //This address was already in the list
362: continue;
363: }
364:
365: if (insertStmt == null) {
366: insertStmt = conn.prepareStatement(insert);
367: }
368: insertStmt.setString(1, senderUser);
369: insertStmt.setString(2, senderHost);
370: insertStmt.setString(3, recipientUser);
371: insertStmt.setString(4, recipientHost);
372: insertStmt.executeUpdate();
373: dbUpdated = true;
374:
375: } finally {
376: theJDBCUtil.closeJDBCResultSet(selectRS);
377: }
378:
379: //Commit our changes if necessary.
380: if (conn != null && dbUpdated && !conn.getAutoCommit()) {
381: conn.commit();
382: dbUpdated = false;
383: }
384: }
385: } catch (SQLException sqle) {
386: log("Error accessing database", sqle);
387: throw new MessagingException("Exception thrown", sqle);
388: } finally {
389: theJDBCUtil.closeJDBCStatement(selectStmt);
390: theJDBCUtil.closeJDBCStatement(insertStmt);
391: //Rollback our changes if necessary.
392: try {
393: if (conn != null && dbUpdated && !conn.getAutoCommit()) {
394: conn.rollback();
395: dbUpdated = false;
396: }
397: } catch (Exception e) {
398: }
399: theJDBCUtil.closeJDBCConnection(conn);
400: }
401: }
402:
403: /** Manages a display request.
404: */
405: private void manageDisplayRequest(Mail mail)
406: throws MessagingException {
407: MailAddress senderMailAddress = mail.getSender();
408: String senderUser = senderMailAddress.getUser().toLowerCase(
409: Locale.US);
410: String senderHost = senderMailAddress.getHost().toLowerCase(
411: Locale.US);
412:
413: senderUser = getPrimaryName(senderUser);
414:
415: Connection conn = null;
416: PreparedStatement selectStmt = null;
417: ResultSet selectRS = null;
418:
419: StringWriter sout = new StringWriter();
420: PrintWriter out = new PrintWriter(sout, true);
421:
422: try {
423: out.println("Answering on behalf of: "
424: + whitelistManagerAddress);
425: out.println("Displaying white list of "
426: + (new MailAddress(senderUser, senderHost)) + ":");
427: out.println();
428:
429: conn = datasource.getConnection();
430: selectStmt = conn.prepareStatement(selectBySender);
431: selectStmt.setString(1, senderUser);
432: selectStmt.setString(2, senderHost);
433: selectRS = selectStmt.executeQuery();
434: while (selectRS.next()) {
435: MailAddress mailAddress = new MailAddress(selectRS
436: .getString(1), selectRS.getString(2));
437: out.println(mailAddress.toInternetAddress().toString());
438: }
439:
440: out.println();
441: out.println("Finished");
442:
443: sendReplyFromPostmaster(mail, sout.toString());
444:
445: } catch (SQLException sqle) {
446: out.println("Error accessing the database");
447: sendReplyFromPostmaster(mail, sout.toString());
448: throw new MessagingException("Error accessing database",
449: sqle);
450: } finally {
451: theJDBCUtil.closeJDBCResultSet(selectRS);
452: theJDBCUtil.closeJDBCStatement(selectStmt);
453: theJDBCUtil.closeJDBCConnection(conn);
454: }
455: }
456:
457: /** Manages an insert request.
458: */
459: private void manageInsertRequest(Mail mail)
460: throws MessagingException {
461: MailAddress senderMailAddress = mail.getSender();
462: String senderUser = senderMailAddress.getUser().toLowerCase(
463: Locale.US);
464: String senderHost = senderMailAddress.getHost().toLowerCase(
465: Locale.US);
466:
467: senderUser = getPrimaryName(senderUser);
468:
469: Connection conn = null;
470: PreparedStatement selectStmt = null;
471: PreparedStatement insertStmt = null;
472: boolean dbUpdated = false;
473:
474: StringWriter sout = new StringWriter();
475: PrintWriter out = new PrintWriter(sout, true);
476:
477: try {
478: out.println("Answering on behalf of: "
479: + whitelistManagerAddress);
480: out.println("Inserting in the white list of "
481: + (new MailAddress(senderUser, senderHost))
482: + " ...");
483: out.println();
484:
485: MimeMessage message = mail.getMessage();
486:
487: Object content = message.getContent();
488:
489: if (message.getContentType().startsWith("text/plain")
490: && content instanceof String) {
491: StringTokenizer st = new StringTokenizer(
492: (String) content, " \t\n\r\f,;:<>");
493: while (st.hasMoreTokens()) {
494: ResultSet selectRS = null;
495: try {
496: MailAddress recipientMailAddress;
497: try {
498: recipientMailAddress = new MailAddress(st
499: .nextToken());
500: } catch (javax.mail.internet.ParseException pe) {
501: continue;
502: }
503: String recipientUser = recipientMailAddress
504: .getUser().toLowerCase(Locale.US);
505: String recipientHost = recipientMailAddress
506: .getHost().toLowerCase(Locale.US);
507:
508: if (getMailetContext().isLocalServer(
509: recipientHost)) {
510: // not a remote recipient, so skip
511: continue;
512: }
513:
514: if (conn == null) {
515: conn = datasource.getConnection();
516: }
517:
518: if (selectStmt == null) {
519: selectStmt = conn
520: .prepareStatement(selectByPK);
521: }
522: selectStmt.setString(1, senderUser);
523: selectStmt.setString(2, senderHost);
524: selectStmt.setString(3, recipientUser);
525: selectStmt.setString(4, recipientHost);
526: selectRS = selectStmt.executeQuery();
527: if (selectRS.next()) {
528: //This address was already in the list
529: out.println("Skipped: "
530: + recipientMailAddress);
531: continue;
532: }
533:
534: if (insertStmt == null) {
535: insertStmt = conn.prepareStatement(insert);
536: }
537: insertStmt.setString(1, senderUser);
538: insertStmt.setString(2, senderHost);
539: insertStmt.setString(3, recipientUser);
540: insertStmt.setString(4, recipientHost);
541: insertStmt.executeUpdate();
542: dbUpdated = true;
543: out
544: .println("Inserted: "
545: + recipientMailAddress);
546:
547: } finally {
548: theJDBCUtil.closeJDBCResultSet(selectRS);
549: }
550: }
551:
552: if (dbUpdated) {
553: log("Insertion request issued by "
554: + senderMailAddress);
555: }
556: //Commit our changes if necessary.
557: if (conn != null && dbUpdated && !conn.getAutoCommit()) {
558: conn.commit();
559: dbUpdated = false;
560: }
561: } else {
562: out.println("The message must be plain - no action");
563: }
564:
565: out.println();
566: out.println("Finished");
567:
568: sendReplyFromPostmaster(mail, sout.toString());
569:
570: } catch (SQLException sqle) {
571: out.println("Error accessing the database");
572: sendReplyFromPostmaster(mail, sout.toString());
573: throw new MessagingException(
574: "Error accessing the database", sqle);
575: } catch (IOException ioe) {
576: out.println("Error getting message content");
577: sendReplyFromPostmaster(mail, sout.toString());
578: throw new MessagingException(
579: "Error getting message content", ioe);
580: } finally {
581: theJDBCUtil.closeJDBCStatement(selectStmt);
582: theJDBCUtil.closeJDBCStatement(insertStmt);
583: //Rollback our changes if necessary.
584: try {
585: if (conn != null && dbUpdated && !conn.getAutoCommit()) {
586: conn.rollback();
587: dbUpdated = false;
588: }
589: } catch (Exception e) {
590: }
591: theJDBCUtil.closeJDBCConnection(conn);
592: }
593: }
594:
595: /** Manages a remove request.
596: */
597: private void manageRemoveRequest(Mail mail)
598: throws MessagingException {
599: MailAddress senderMailAddress = mail.getSender();
600: String senderUser = senderMailAddress.getUser().toLowerCase(
601: Locale.US);
602: String senderHost = senderMailAddress.getHost().toLowerCase(
603: Locale.US);
604:
605: senderUser = getPrimaryName(senderUser);
606:
607: Connection conn = null;
608: PreparedStatement selectStmt = null;
609: PreparedStatement deleteStmt = null;
610: boolean dbUpdated = false;
611:
612: StringWriter sout = new StringWriter();
613: PrintWriter out = new PrintWriter(sout, true);
614:
615: try {
616: out.println("Answering on behalf of: "
617: + whitelistManagerAddress);
618: out.println("Removing from the white list of "
619: + (new MailAddress(senderUser, senderHost))
620: + " ...");
621: out.println();
622:
623: MimeMessage message = mail.getMessage();
624:
625: Object content = message.getContent();
626:
627: if (message.getContentType().startsWith("text/plain")
628: && content instanceof String) {
629: StringTokenizer st = new StringTokenizer(
630: (String) content, " \t\n\r\f,;:<>");
631: while (st.hasMoreTokens()) {
632: ResultSet selectRS = null;
633: try {
634: MailAddress recipientMailAddress;
635: try {
636: recipientMailAddress = new MailAddress(st
637: .nextToken());
638: } catch (javax.mail.internet.ParseException pe) {
639: continue;
640: }
641: String recipientUser = recipientMailAddress
642: .getUser().toLowerCase(Locale.US);
643: String recipientHost = recipientMailAddress
644: .getHost().toLowerCase(Locale.US);
645:
646: if (getMailetContext().isLocalServer(
647: recipientHost)) {
648: // not a remote recipient, so skip
649: continue;
650: }
651:
652: if (conn == null) {
653: conn = datasource.getConnection();
654: }
655:
656: if (selectStmt == null) {
657: selectStmt = conn
658: .prepareStatement(selectByPK);
659: }
660: selectStmt.setString(1, senderUser);
661: selectStmt.setString(2, senderHost);
662: selectStmt.setString(3, recipientUser);
663: selectStmt.setString(4, recipientHost);
664: selectRS = selectStmt.executeQuery();
665: if (!selectRS.next()) {
666: //This address was not in the list
667: out.println("Skipped: "
668: + recipientMailAddress);
669: continue;
670: }
671:
672: if (deleteStmt == null) {
673: deleteStmt = conn
674: .prepareStatement(deleteByPK);
675: }
676: deleteStmt.setString(1, senderUser);
677: deleteStmt.setString(2, senderHost);
678: deleteStmt.setString(3, recipientUser);
679: deleteStmt.setString(4, recipientHost);
680: deleteStmt.executeUpdate();
681: dbUpdated = true;
682: out.println("Removed: " + recipientMailAddress);
683:
684: } finally {
685: theJDBCUtil.closeJDBCResultSet(selectRS);
686: }
687: }
688:
689: if (dbUpdated) {
690: log("Removal request issued by "
691: + senderMailAddress);
692: }
693: //Commit our changes if necessary.
694: if (conn != null && dbUpdated && !conn.getAutoCommit()) {
695: conn.commit();
696: dbUpdated = false;
697: }
698: } else {
699: out.println("The message must be plain - no action");
700: }
701:
702: out.println();
703: out.println("Finished");
704:
705: sendReplyFromPostmaster(mail, sout.toString());
706:
707: } catch (SQLException sqle) {
708: out.println("Error accessing the database");
709: sendReplyFromPostmaster(mail, sout.toString());
710: throw new MessagingException(
711: "Error accessing the database", sqle);
712: } catch (IOException ioe) {
713: out.println("Error getting message content");
714: sendReplyFromPostmaster(mail, sout.toString());
715: throw new MessagingException(
716: "Error getting message content", ioe);
717: } finally {
718: theJDBCUtil.closeJDBCStatement(selectStmt);
719: theJDBCUtil.closeJDBCStatement(deleteStmt);
720: //Rollback our changes if necessary.
721: try {
722: if (conn != null && dbUpdated && !conn.getAutoCommit()) {
723: conn.rollback();
724: dbUpdated = false;
725: }
726: } catch (Exception e) {
727: }
728: theJDBCUtil.closeJDBCConnection(conn);
729: }
730: }
731:
732: private void sendReplyFromPostmaster(Mail mail, String stringContent)
733: throws MessagingException {
734: try {
735: MailAddress notifier = getMailetContext().getPostmaster();
736:
737: MailAddress senderMailAddress = mail.getSender();
738:
739: MimeMessage message = mail.getMessage();
740: //Create the reply message
741: MimeMessage reply = new MimeMessage(Session
742: .getDefaultInstance(System.getProperties(), null));
743:
744: //Create the list of recipients in the Address[] format
745: InternetAddress[] rcptAddr = new InternetAddress[1];
746: rcptAddr[0] = senderMailAddress.toInternetAddress();
747: reply.setRecipients(Message.RecipientType.TO, rcptAddr);
748:
749: //Set the sender...
750: reply.setFrom(notifier.toInternetAddress());
751:
752: //Create the message body
753: MimeMultipart multipart = new MimeMultipart();
754: //Add message as the first mime body part
755: MimeBodyPart part = new MimeBodyPart();
756: part.setContent(stringContent, "text/plain");
757: part.setHeader(RFC2822Headers.CONTENT_TYPE, "text/plain");
758: multipart.addBodyPart(part);
759:
760: reply.setContent(multipart);
761: reply.setHeader(RFC2822Headers.CONTENT_TYPE, multipart
762: .getContentType());
763:
764: //Create the list of recipients in our MailAddress format
765: Set recipients = new HashSet();
766: recipients.add(senderMailAddress);
767:
768: //Set additional headers
769: if (reply.getHeader(RFC2822Headers.DATE) == null) {
770: reply.setHeader(RFC2822Headers.DATE, rfc822DateFormat
771: .format(new java.util.Date()));
772: }
773: String subject = message.getSubject();
774: if (subject == null) {
775: subject = "";
776: }
777: if (subject.indexOf("Re:") == 0) {
778: reply.setSubject(subject);
779: } else {
780: reply.setSubject("Re:" + subject);
781: }
782: reply.setHeader(RFC2822Headers.IN_REPLY_TO, message
783: .getMessageID());
784:
785: //Send it off...
786: getMailetContext().sendMail(notifier, recipients, reply);
787: } catch (Exception e) {
788: log("Exception found sending reply", e);
789: }
790: }
791:
792: /** Gets the main name of a local customer, handling alias */
793: private String getPrimaryName(String originalUsername) {
794: String username;
795: try {
796: username = localusers.getRealName(originalUsername);
797: JamesUser user = (JamesUser) localusers
798: .getUserByName(username);
799: if (user.getAliasing()) {
800: username = user.getAlias();
801: }
802: } catch (Exception e) {
803: username = originalUsername;
804: }
805: return username;
806: }
807:
808: /**
809: * Initializes the sql query environment from the SqlResources file.
810: * Will look for conf/sqlResources.xml.
811: * @param conn The connection for accessing the database
812: * @param mailetContext The current mailet context,
813: * for finding the conf/sqlResources.xml file
814: * @throws Exception If any error occurs
815: */
816: public void initSqlQueries(Connection conn,
817: org.apache.mailet.MailetContext mailetContext)
818: throws Exception {
819: try {
820: if (conn.getAutoCommit()) {
821: conn.setAutoCommit(false);
822: }
823:
824: this .sqlFile = new File((String) mailetContext
825: .getAttribute("confDir"), "sqlResources.xml")
826: .getCanonicalFile();
827: sqlQueries.init(this .sqlFile, "WhiteList", conn,
828: getSqlParameters());
829:
830: checkTables(conn);
831: } finally {
832: theJDBCUtil.closeJDBCConnection(conn);
833: }
834: }
835:
836: private void checkTables(Connection conn) throws SQLException {
837: DatabaseMetaData dbMetaData = conn.getMetaData();
838: // Need to ask in the case that identifiers are stored, ask the DatabaseMetaInfo.
839: // Try UPPER, lower, and MixedCase, to see if the table is there.
840:
841: boolean dbUpdated = false;
842:
843: dbUpdated = createTable(conn, "whiteListTableName",
844: "createWhiteListTable");
845:
846: //Commit our changes if necessary.
847: if (conn != null && dbUpdated && !conn.getAutoCommit()) {
848: conn.commit();
849: dbUpdated = false;
850: }
851:
852: }
853:
854: private boolean createTable(Connection conn,
855: String tableNameSqlStringName, String createSqlStringName)
856: throws SQLException {
857: String tableName = sqlQueries.getSqlString(
858: tableNameSqlStringName, true);
859:
860: DatabaseMetaData dbMetaData = conn.getMetaData();
861:
862: // Try UPPER, lower, and MixedCase, to see if the table is there.
863: if (theJDBCUtil.tableExists(dbMetaData, tableName)) {
864: return false;
865: }
866:
867: PreparedStatement createStatement = null;
868:
869: try {
870: createStatement = conn.prepareStatement(sqlQueries
871: .getSqlString(createSqlStringName, true));
872: createStatement.execute();
873:
874: StringBuffer logBuffer = null;
875: logBuffer = new StringBuffer(64).append("Created table '")
876: .append(tableName).append(
877: "' using sqlResources string '").append(
878: createSqlStringName).append("'.");
879: log(logBuffer.toString());
880:
881: } finally {
882: theJDBCUtil.closeJDBCStatement(createStatement);
883: }
884:
885: return true;
886: }
887:
888: }
|