Source Code Cross Referenced for AbstractRedirect.java in  » Web-Mail » james-2.3.1 » org » apache » james » transport » mailets » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Mail » james 2.3.1 » org.apache.james.transport.mailets 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /****************************************************************
0002:         * Licensed to the Apache Software Foundation (ASF) under one   *
0003:         * or more contributor license agreements.  See the NOTICE file *
0004:         * distributed with this work for additional information        *
0005:         * regarding copyright ownership.  The ASF licenses this file   *
0006:         * to you under the Apache License, Version 2.0 (the            *
0007:         * "License"); you may not use this file except in compliance   *
0008:         * with the License.  You may obtain a copy of the License at   *
0009:         *                                                              *
0010:         *   http://www.apache.org/licenses/LICENSE-2.0                 *
0011:         *                                                              *
0012:         * Unless required by applicable law or agreed to in writing,   *
0013:         * software distributed under the License is distributed on an  *
0014:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
0015:         * KIND, either express or implied.  See the License for the    *
0016:         * specific language governing permissions and limitations      *
0017:         * under the License.                                           *
0018:         ****************************************************************/package org.apache.james.transport.mailets;
0019:
0020:        import java.io.PrintWriter;
0021:        import java.io.StringWriter;
0022:
0023:        import java.util.Collection;
0024:        import java.util.Date;
0025:        import java.util.Enumeration;
0026:        import java.util.HashSet;
0027:        import java.util.Iterator;
0028:        import java.util.Locale;
0029:        import java.util.ArrayList;
0030:
0031:        import javax.mail.Message;
0032:        import javax.mail.MessagingException;
0033:        import javax.mail.internet.ParseException;
0034:        import javax.mail.Session;
0035:        import javax.mail.internet.InternetAddress;
0036:        import javax.mail.internet.MimeBodyPart;
0037:        import javax.mail.internet.MimeMessage;
0038:        import javax.mail.internet.MimeMultipart;
0039:
0040:        import org.apache.mailet.RFC2822Headers;
0041:        import org.apache.mailet.dates.RFC822DateFormat;
0042:        import org.apache.james.core.MailImpl;
0043:        import org.apache.james.core.MimeMessageUtil;
0044:
0045:        import org.apache.mailet.GenericMailet;
0046:        import org.apache.mailet.Mail;
0047:        import org.apache.mailet.MailAddress;
0048:
0049:        /**
0050:         * <P>Abstract mailet providing configurable redirection services.<BR>
0051:         * This mailet can be subclassed to make authoring redirection mailets simple.<BR>
0052:         * By extending it and overriding one or more of these methods new behaviour can
0053:         * be quickly created without the author having to address any other issue than
0054:         * the relevant one:</P>
0055:         * <UL>
0056:         * <LI>attachError() , should error messages be appended to the message</LI>
0057:         * <LI>getAttachmentType(), what should be attached to the message</LI>
0058:         * <LI>getInLineType(), what should be included in the message</LI>
0059:         * <LI>getMessage(), The text of the message itself</LI>
0060:         * <LI>getRecipients(), the recipients the mail is sent to</LI>
0061:         * <LI>getReplyTo(), where replies to this message will be sent</LI>
0062:         * <LI>getReversePath(), what to set the reverse-path to</LI>
0063:         * <LI>getSender(), who the mail is from</LI>
0064:         * <LI>getSubject(), a string to replace the message subject</LI>
0065:         * <LI>getSubjectPrefix(), a prefix to be added to the message subject, possibly already replaced by a new subject</LI>
0066:         * <LI>getTo(), a list of people to whom the mail is *apparently* sent</LI>
0067:         * <LI>isReply(), should this mailet set the IN_REPLY_TO header to the id of the current message</LI>
0068:         * <LI>getPassThrough(), should this mailet allow the original message to continue processing or GHOST it.</LI>
0069:         * <LI>getFakeDomainCheck(), should this mailet check if the sender domain address is valid.</LI>
0070:         * <LI>isStatic(), should this mailet run the get methods for every mail, or just once.</LI>
0071:         * </UL>
0072:         * <P>For each of the methods above (generically called "getX()" methods in this class
0073:         * and its subclasses), there is an associated "getX(Mail)" method and most times
0074:         * a "setX(Mail, Tx, Mail)" method.<BR>
0075:         * The roles are the following:</P>
0076:         * <UL>
0077:         * <LI>a "getX()" method returns the correspondent "X" value that can be evaluated "statically"
0078:         * once at init time and then stored in a variable and made available for later use by a
0079:         * "getX(Mail)" method;</LI>
0080:         * <LI>a "getX(Mail)" method is the one called to return the correspondent "X" value
0081:         * that can be evaluated "dynamically", tipically based on the currently serviced mail;
0082:         * the default behaviour is to return the value of getX();</LI>
0083:         * <LI>a "setX(Mail, Tx, Mail)" method is called to change the correspondent "X" value
0084:         * of the redirected Mail object, using the value returned by "gexX(Mail)";
0085:         * if such value is null, it does nothing.</LI>
0086:         * </UL>
0087:         * <P>Here follows the typical pattern of those methods:</P>
0088:         * <PRE><CODE>
0089:         *    ...
0090:         *    Tx x;
0091:         *    ...
0092:         *    protected boolean getX(Mail originalMail) throws MessagingException {
0093:         *        boolean x = (isStatic()) ? this.x : getX();
0094:         *        ...
0095:         *        return x;
0096:         *    }
0097:         *    ...
0098:         *    public void init() throws MessagingException {
0099:         *        ...
0100:         *        isStatic = (getInitParameter("static") == null) ? false : new Boolean(getInitParameter("static")).booleanValue();
0101:         *        if(isStatic()) {
0102:         *            ...
0103:         *            X  = getX();
0104:         *            ...
0105:         *        }
0106:         *    ...
0107:         *    public void service(Mail originalMail) throws MessagingException {
0108:         *    ...
0109:         *    setX(newMail, getX(originalMail), originalMail);
0110:         *    ...
0111:         *    }
0112:         *    ...
0113:         * </CODE></PRE>
0114:         * <P>The <I>isStatic</I> variable and method is used to allow for the situations
0115:         * (deprecated since version 2.2, but possibly used by previoulsy written extensions
0116:         * to {@link Redirect}) in which the getX() methods are non static: in this case
0117:         * {@link #isStatic()} must return false.<BR>
0118:         * Finally, a "getX()" method may return a "special address" (see {@link SpecialAddress}),
0119:         * that later will be resolved ("late bound") by a "getX(Mail)" or "setX(Mail, Tx, Mail)":
0120:         * it is a dynamic value that does not require <CODE>isStatic</CODE> to be false.</P>
0121:         *
0122:         * <P>Supports by default the <CODE>passThrough</CODE> init parameter (false if missing).
0123:         * Subclasses can override this behaviour overriding {@link #getPassThrough()}.</P>
0124:         *
0125:         * @version CVS $Revision: 494012 $ $Date: 2007-01-08 11:23:58 +0100 (Mo, 08 Jan 2007) $
0126:         * @since 2.2.0
0127:         */
0128:
0129:        public abstract class AbstractRedirect extends GenericMailet {
0130:
0131:            /**
0132:             * Gets the expected init parameters.
0133:             *
0134:             * @return null meaning no check
0135:             */
0136:            protected String[] getAllowedInitParameters() {
0137:                return null;
0138:            }
0139:
0140:            /**
0141:             * Controls certain log messages.
0142:             */
0143:            protected boolean isDebug = false;
0144:
0145:            /**
0146:             * Holds the value of the <CODE>static</CODE> init parameter.
0147:             */
0148:            protected boolean isStatic = false;
0149:
0150:            private static class AddressMarker {
0151:                public static MailAddress SENDER;
0152:                public static MailAddress REVERSE_PATH;
0153:                public static MailAddress FROM;
0154:                public static MailAddress REPLY_TO;
0155:                public static MailAddress TO;
0156:                public static MailAddress RECIPIENTS;
0157:                public static MailAddress DELETE;
0158:                public static MailAddress UNALTERED;
0159:                public static MailAddress NULL;
0160:
0161:                static {
0162:                    try {
0163:                        SENDER = new MailAddress("sender", "address.marker");
0164:                        REVERSE_PATH = new MailAddress("reverse.path",
0165:                                "address.marker");
0166:                        FROM = new MailAddress("from", "address.marker");
0167:                        REPLY_TO = new MailAddress("reply.to", "address.marker");
0168:                        TO = new MailAddress("to", "address.marker");
0169:                        RECIPIENTS = new MailAddress("recipients",
0170:                                "address.marker");
0171:                        DELETE = new MailAddress("delete", "address.marker");
0172:                        UNALTERED = new MailAddress("unaltered",
0173:                                "address.marker");
0174:                        NULL = new MailAddress("null", "address.marker");
0175:
0176:                    } catch (Exception _) {
0177:                    }
0178:                }
0179:            }
0180:
0181:            /**
0182:             * Class containing "special addresses" constants.
0183:             * Such addresses mean dynamic values that later will be resolved ("late bound")
0184:             * by a "getX(Mail)" or "setX(Mail, Tx, Mail)".
0185:             */
0186:            protected static class SpecialAddress {
0187:                public static final MailAddress SENDER = AddressMarker.SENDER;
0188:                public static final MailAddress REVERSE_PATH = AddressMarker.REVERSE_PATH;
0189:                public static final MailAddress FROM = AddressMarker.FROM;
0190:                public static final MailAddress REPLY_TO = AddressMarker.REPLY_TO;
0191:                public static final MailAddress TO = AddressMarker.TO;
0192:                public static final MailAddress RECIPIENTS = AddressMarker.RECIPIENTS;
0193:                public static final MailAddress DELETE = AddressMarker.DELETE;
0194:                public static final MailAddress UNALTERED = AddressMarker.UNALTERED;
0195:                public static final MailAddress NULL = AddressMarker.NULL;
0196:            }
0197:
0198:            // The values that indicate how to attach the original mail
0199:            // to the new mail.
0200:
0201:            protected static final int UNALTERED = 0;
0202:
0203:            protected static final int HEADS = 1;
0204:
0205:            protected static final int BODY = 2;
0206:
0207:            protected static final int ALL = 3;
0208:
0209:            protected static final int NONE = 4;
0210:
0211:            protected static final int MESSAGE = 5;
0212:
0213:            private boolean passThrough = false;
0214:            private boolean fakeDomainCheck = true;
0215:            private int attachmentType = NONE;
0216:            private int inLineType = BODY;
0217:            private String messageText;
0218:            private Collection recipients;
0219:            private MailAddress replyTo;
0220:            private MailAddress reversePath;
0221:            private MailAddress sender;
0222:            private String subject;
0223:            private String subjectPrefix;
0224:            private InternetAddress[] apparentlyTo;
0225:            private boolean attachError = false;
0226:            private boolean isReply = false;
0227:
0228:            private RFC822DateFormat rfc822DateFormat = new RFC822DateFormat();
0229:
0230:            /* ******************************************************************** */
0231:            /* ****************** Begin of getX and setX methods ****************** */
0232:            /* ******************************************************************** */
0233:
0234:            /**
0235:             * <P>Gets the <CODE>static</CODE> property.</P>
0236:             * <P>Return true to reduce calls to getTo, getSender, getRecipients, getReplyTo, getReversePath amd getMessage
0237:             * where these values don't change (eg hard coded, or got at startup from the mailet config);
0238:             * return false where any of these methods generate their results dynamically eg in response to the message being processed,
0239:             * or by reference to a repository of users.</P>
0240:             * <P>It is now (from version 2.2) somehow obsolete, as should be always true because the "good practice"
0241:             * is to use "getX()" methods statically, and use instead "getX(Mail)" methods for dynamic situations.
0242:             * A false value is now meaningful only for subclasses of {@link Redirect} older than version 2.2
0243:             * that were relying on this.</P>
0244:             *
0245:             * <P>Is a "getX()" method.</P>
0246:             *
0247:             * @return true, as normally "getX()" methods shouls be static
0248:             */
0249:            protected boolean isStatic() {
0250:                return true;
0251:            }
0252:
0253:            /**
0254:             * Gets the <CODE>passThrough</CODE> property.
0255:             * Return true to allow the original message to continue through the processor, false to GHOST it.
0256:             * Is a "getX()" method.
0257:             *
0258:             * @return the <CODE>passThrough</CODE> init parameter, or false if missing
0259:             */
0260:            protected boolean getPassThrough() throws MessagingException {
0261:                return new Boolean(getInitParameter("passThrough"))
0262:                        .booleanValue();
0263:            }
0264:
0265:            /**
0266:             * Gets the <CODE>passThrough</CODE> property,
0267:             * built dynamically using the original Mail object.
0268:             * Is a "getX(Mail)" method.
0269:             *
0270:             * @return {@link #getPassThrough()}
0271:             */
0272:            protected boolean getPassThrough(Mail originalMail)
0273:                    throws MessagingException {
0274:                return (isStatic()) ? this .passThrough : getPassThrough();
0275:            }
0276:
0277:            /**
0278:             * Gets the <CODE>fakeDomainCheck</CODE> property.
0279:             * Return true to check if the sender domain is valid.
0280:             * Is a "getX()" method.
0281:             *
0282:             * @return the <CODE>fakeDomainCheck</CODE> init parameter, or true if missing
0283:             */
0284:            protected boolean getFakeDomainCheck() throws MessagingException {
0285:                return new Boolean(getInitParameter("fakeDomainCheck"))
0286:                        .booleanValue();
0287:            }
0288:
0289:            /**
0290:             * Gets the <CODE>fakeDomainCheck</CODE> property,
0291:             * built dynamically using the original Mail object.
0292:             * Is a "getX(Mail)" method.
0293:             *
0294:             * @return {@link #getFakeDomainCheck()}
0295:             */
0296:            protected boolean getFakeDomainCheck(Mail originalMail)
0297:                    throws MessagingException {
0298:                return (isStatic()) ? this .fakeDomainCheck
0299:                        : getFakeDomainCheck();
0300:            }
0301:
0302:            /**
0303:             * Gets the <CODE>inline</CODE> property.
0304:             * May return one of the following values to indicate how to append the original message
0305:             * to build the new message:
0306:             * <ul>
0307:             *    <li><CODE>UNALTERED</CODE> : original message is the new message body</li>
0308:             *    <li><CODE>BODY</CODE> : original message body is appended to the new message</li>
0309:             *    <li><CODE>HEADS</CODE> : original message headers are appended to the new message</li>
0310:             *    <li><CODE>ALL</CODE> : original is appended with all headers</li>
0311:             *    <li><CODE>NONE</CODE> : original is not appended</li>
0312:             * </ul>
0313:             * Is a "getX()" method.
0314:             *
0315:             * @return the <CODE>inline</CODE> init parameter, or <CODE>UNALTERED</CODE> if missing
0316:             */
0317:            protected int getInLineType() throws MessagingException {
0318:                return getTypeCode(getInitParameter("inline", "unaltered"));
0319:            }
0320:
0321:            /**
0322:             * Gets the <CODE>inline</CODE> property,
0323:             * built dynamically using the original Mail object.
0324:             * Is a "getX(Mail)" method.
0325:             *
0326:             * @return {@link #getInLineType()}
0327:             */
0328:            protected int getInLineType(Mail originalMail)
0329:                    throws MessagingException {
0330:                return (isStatic()) ? this .inLineType : getInLineType();
0331:            }
0332:
0333:            /** Gets the <CODE>attachment</CODE> property.
0334:             * May return one of the following values to indicate how to attach the original message
0335:             * to the new message:
0336:             * <ul>
0337:             *    <li><CODE>BODY</CODE> : original message body is attached as plain text to the new message</li>
0338:             *    <li><CODE>HEADS</CODE> : original message headers are attached as plain text to the new message</li>
0339:             *    <li><CODE>ALL</CODE> : original is attached as plain text with all headers</li>
0340:             *    <li><CODE>MESSAGE</CODE> : original message is attached as type message/rfc822, a complete mail message.</li>
0341:             *    <li><CODE>NONE</CODE> : original is not attached</li>
0342:             * </ul>
0343:             * Is a "getX()" method.
0344:             *
0345:             * @return the <CODE>attachment</CODE> init parameter, or <CODE>NONE</CODE> if missing
0346:             */
0347:            protected int getAttachmentType() throws MessagingException {
0348:                return getTypeCode(getInitParameter("attachment", "none"));
0349:            }
0350:
0351:            /**
0352:             * Gets the <CODE>attachment</CODE> property,
0353:             * built dynamically using the original Mail object.
0354:             * Is a "getX(Mail)" method.
0355:             *
0356:             * @return {@link #getAttachmentType()}
0357:             */
0358:            protected int getAttachmentType(Mail originalMail)
0359:                    throws MessagingException {
0360:                return (isStatic()) ? this .attachmentType : getAttachmentType();
0361:            }
0362:
0363:            /**
0364:             * Gets the <CODE>message</CODE> property.
0365:             * Returns a message to which the original message can be attached/appended
0366:             * to build the new message.
0367:             * Is a "getX()" method.
0368:             *
0369:             * @return the <CODE>message</CODE> init parameter or an empty string if missing
0370:             */
0371:            protected String getMessage() throws MessagingException {
0372:                return getInitParameter("message", "");
0373:            }
0374:
0375:            /**
0376:             * Gets the <CODE>message</CODE> property,
0377:             * built dynamically using the original Mail object.
0378:             * Is a "getX(Mail)" method.
0379:             *
0380:             * @return {@link #getMessage()}
0381:             */
0382:            protected String getMessage(Mail originalMail)
0383:                    throws MessagingException {
0384:                return (isStatic()) ? this .messageText : getMessage();
0385:            }
0386:
0387:            /**
0388:             * Gets the <CODE>recipients</CODE> property.
0389:             * Returns the collection of recipients of the new message,
0390:             * or null if no change is requested.
0391:             * Is a "getX()" method.
0392:             *
0393:             * @return the <CODE>recipients</CODE> init parameter
0394:             * or the postmaster address
0395:             * or <CODE>SpecialAddress.SENDER</CODE>
0396:             * or <CODE>SpecialAddress.FROM</CODE>
0397:             * or <CODE>SpecialAddress.REPLY_TO</CODE>
0398:             * or <CODE>SpecialAddress.REVERSE_PATH</CODE>
0399:             * or <CODE>SpecialAddress.UNALTERED</CODE>
0400:             * or <CODE>SpecialAddress.RECIPIENTS</CODE>
0401:             * or <CODE>null</CODE> if missing
0402:             */
0403:            protected Collection getRecipients() throws MessagingException {
0404:                Collection newRecipients = new HashSet();
0405:                String addressList = getInitParameter("recipients");
0406:
0407:                // if nothing was specified, return <CODE>null</CODE> meaning no change
0408:                if (addressList == null) {
0409:                    return null;
0410:                }
0411:
0412:                try {
0413:                    InternetAddress[] iaarray = InternetAddress.parse(
0414:                            addressList, false);
0415:                    for (int i = 0; i < iaarray.length; i++) {
0416:                        String addressString = iaarray[i].getAddress();
0417:                        MailAddress specialAddress = getSpecialAddress(
0418:                                addressString, new String[] { "postmaster",
0419:                                        "sender", "from", "replyTo",
0420:                                        "reversePath", "unaltered",
0421:                                        "recipients", "to", "null" });
0422:                        if (specialAddress != null) {
0423:                            newRecipients.add(specialAddress);
0424:                        } else {
0425:                            newRecipients.add(new MailAddress(iaarray[i]));
0426:                        }
0427:                    }
0428:                } catch (Exception e) {
0429:                    throw new MessagingException(
0430:                            "Exception thrown in getRecipients() parsing: "
0431:                                    + addressList, e);
0432:                }
0433:                if (newRecipients.size() == 0) {
0434:                    throw new MessagingException(
0435:                            "Failed to initialize \"recipients\" list; empty <recipients> init parameter found.");
0436:                }
0437:
0438:                return newRecipients;
0439:            }
0440:
0441:            /**
0442:             * Gets the <CODE>recipients</CODE> property,
0443:             * built dynamically using the original Mail object.
0444:             * Is a "getX(Mail)" method.
0445:             *
0446:             * @return {@link #replaceMailAddresses} on {@link #getRecipients()},
0447:             */
0448:            protected Collection getRecipients(Mail originalMail)
0449:                    throws MessagingException {
0450:                Collection recipients = (isStatic()) ? this .recipients
0451:                        : getRecipients();
0452:                if (recipients != null) {
0453:                    if (recipients.size() == 1
0454:                            && (recipients.contains(SpecialAddress.UNALTERED) || recipients
0455:                                    .contains(SpecialAddress.RECIPIENTS))) {
0456:                        recipients = null;
0457:                    } else {
0458:                        recipients = replaceMailAddresses(originalMail,
0459:                                recipients);
0460:                    }
0461:                }
0462:                return recipients;
0463:            }
0464:
0465:            /**
0466:             * Sets the recipients of <I>newMail</I> to <I>recipients</I>.
0467:             * If the requested value is null does nothing.
0468:             * Is a "setX(Mail, Tx, Mail)" method.
0469:             */
0470:            protected void setRecipients(Mail newMail, Collection recipients,
0471:                    Mail originalMail) throws MessagingException {
0472:                if (recipients != null) {
0473:                    newMail.setRecipients(recipients);
0474:                    if (isDebug) {
0475:                        log("recipients set to: "
0476:                                + arrayToString(recipients.toArray()));
0477:                    }
0478:                }
0479:            }
0480:
0481:            /**
0482:             * Gets the <CODE>to</CODE> property.
0483:             * Returns the "To:" recipients of the new message.
0484:             * or null if no change is requested.
0485:             * Is a "getX()" method.
0486:             *
0487:             * @return the <CODE>to</CODE> init parameter
0488:             * or the postmaster address
0489:             * or <CODE>SpecialAddress.SENDER</CODE>
0490:             * or <CODE>SpecialAddress.REVERSE_PATH</CODE>
0491:             * or <CODE>SpecialAddress.FROM</CODE>
0492:             * or <CODE>SpecialAddress.REPLY_TO</CODE>
0493:             * or <CODE>SpecialAddress.UNALTERED</CODE>
0494:             * or <CODE>SpecialAddress.TO</CODE>
0495:             * or <CODE>null</CODE> if missing
0496:             */
0497:            protected InternetAddress[] getTo() throws MessagingException {
0498:                InternetAddress[] iaarray = null;
0499:                String addressList = getInitParameter("to");
0500:
0501:                // if nothing was specified, return null meaning no change
0502:                if (addressList == null) {
0503:                    return null;
0504:                }
0505:
0506:                try {
0507:                    iaarray = InternetAddress.parse(addressList, false);
0508:                    for (int i = 0; i < iaarray.length; ++i) {
0509:                        String addressString = iaarray[i].getAddress();
0510:                        MailAddress specialAddress = getSpecialAddress(
0511:                                addressString, new String[] { "postmaster",
0512:                                        "sender", "from", "replyTo",
0513:                                        "reversePath", "unaltered",
0514:                                        "recipients", "to", "null" });
0515:                        if (specialAddress != null) {
0516:                            iaarray[i] = specialAddress.toInternetAddress();
0517:                        }
0518:                    }
0519:                } catch (Exception e) {
0520:                    throw new MessagingException(
0521:                            "Exception thrown in getTo() parsing: "
0522:                                    + addressList, e);
0523:                }
0524:                if (iaarray.length == 0) {
0525:                    throw new MessagingException(
0526:                            "Failed to initialize \"to\" list; empty <to> init parameter found.");
0527:                }
0528:
0529:                return iaarray;
0530:            }
0531:
0532:            /**
0533:             * Gets the <CODE>to</CODE> property,
0534:             * built dynamically using the original Mail object.
0535:             * Its outcome will be the the value the <I>TO:</I> header will be set to,
0536:             * that could be different from the real recipient (see {@link #getRecipients}).
0537:             * Is a "getX(Mail)" method.
0538:             *
0539:             * @return {@link #replaceInternetAddresses} on {@link #getRecipients()},
0540:             */
0541:            protected InternetAddress[] getTo(Mail originalMail)
0542:                    throws MessagingException {
0543:                InternetAddress[] apparentlyTo = (isStatic()) ? this .apparentlyTo
0544:                        : getTo();
0545:                if (apparentlyTo != null) {
0546:                    if (apparentlyTo.length == 1
0547:                            && (apparentlyTo[0].equals(SpecialAddress.UNALTERED
0548:                                    .toInternetAddress()) || apparentlyTo[0]
0549:                                    .equals(SpecialAddress.TO
0550:                                            .toInternetAddress()))) {
0551:                        apparentlyTo = null;
0552:                    } else {
0553:                        Collection toList = new ArrayList(apparentlyTo.length);
0554:                        for (int i = 0; i < apparentlyTo.length; i++) {
0555:                            toList.add(apparentlyTo[i]);
0556:                        }
0557:                        /* IMPORTANT: setTo() treats null differently from a zero length array,
0558:                          so it's ok to get a zero length array from replaceSpecialAddresses
0559:                         */
0560:                        apparentlyTo = (InternetAddress[]) replaceInternetAddresses(
0561:                                originalMail, toList).toArray(
0562:                                new InternetAddress[0]);
0563:                    }
0564:                }
0565:
0566:                return apparentlyTo;
0567:            }
0568:
0569:            /**
0570:             * Sets the "To:" header of <I>newMail</I> to <I>to</I>.
0571:             * If the requested value is null does nothing.
0572:             * Is a "setX(Mail, Tx, Mail)" method.
0573:             */
0574:            protected void setTo(Mail newMail, InternetAddress[] to,
0575:                    Mail originalMail) throws MessagingException {
0576:                if (to != null) {
0577:                    newMail.getMessage().setRecipients(
0578:                            Message.RecipientType.TO, to);
0579:                    if (isDebug) {
0580:                        log("apparentlyTo set to: " + arrayToString(to));
0581:                    }
0582:                }
0583:            }
0584:
0585:            /**
0586:             * Gets the <CODE>replyto</CODE> property.
0587:             * Returns the Reply-To address of the new message,
0588:             * or null if no change is requested.
0589:             * Is a "getX()" method.
0590:             *
0591:             * @return the <CODE>replyto</CODE> init parameter
0592:             * or the postmaster address
0593:             * or <CODE>SpecialAddress.SENDER</CODE>
0594:             * or <CODE>SpecialAddress.UNALTERED</CODE>
0595:             * or <CODE>SpecialAddress.NULL</CODE>
0596:             * or <CODE>null</CODE> if missing
0597:             */
0598:            protected MailAddress getReplyTo() throws MessagingException {
0599:                String addressString = getInitParameter("replyTo",
0600:                        getInitParameter("replyto"));
0601:
0602:                if (addressString != null) {
0603:                    MailAddress specialAddress = getSpecialAddress(
0604:                            addressString, new String[] { "postmaster",
0605:                                    "sender", "null", "unaltered" });
0606:                    if (specialAddress != null) {
0607:                        return specialAddress;
0608:                    }
0609:
0610:                    try {
0611:                        return new MailAddress(addressString);
0612:                    } catch (Exception e) {
0613:                        throw new MessagingException(
0614:                                "Exception thrown in getReplyTo() parsing: "
0615:                                        + addressString, e);
0616:                    }
0617:                }
0618:
0619:                return null;
0620:            }
0621:
0622:            /**
0623:             * Gets the <CODE>replyTo</CODE> property,
0624:             * built dynamically using the original Mail object.
0625:             * Is a "getX(Mail)" method.
0626:             *
0627:             * @return {@link #getReplyTo()}
0628:             * replacing <CODE>SpecialAddress.UNALTERED</CODE> if applicable with null
0629:             * and <CODE>SpecialAddress.SENDER</CODE> with the original mail sender
0630:             */
0631:            protected MailAddress getReplyTo(Mail originalMail)
0632:                    throws MessagingException {
0633:                MailAddress replyTo = (isStatic()) ? this .replyTo
0634:                        : getReplyTo();
0635:                if (replyTo != null) {
0636:                    if (replyTo == SpecialAddress.UNALTERED) {
0637:                        replyTo = null;
0638:                    } else if (replyTo == SpecialAddress.SENDER) {
0639:                        replyTo = originalMail.getSender();
0640:                    }
0641:                }
0642:                return replyTo;
0643:            }
0644:
0645:            /**
0646:             * <P>Sets the "Reply-To:" header of <I>newMail</I> to <I>replyTo</I>.</P>
0647:             * If the requested value is <CODE>SpecialAddress.NULL</CODE> will remove the "Reply-To:" header.
0648:             * If the requested value is null does nothing.</P>
0649:             * Is a "setX(Mail, Tx, Mail)" method.
0650:             */
0651:            protected void setReplyTo(Mail newMail, MailAddress replyTo,
0652:                    Mail originalMail) throws MessagingException {
0653:                if (replyTo != null) {
0654:                    InternetAddress[] iart = null;
0655:                    if (replyTo != SpecialAddress.NULL) {
0656:                        iart = new InternetAddress[1];
0657:                        iart[0] = replyTo.toInternetAddress();
0658:                    }
0659:
0660:                    // Note: if iart is null will remove the header
0661:                    newMail.getMessage().setReplyTo(iart);
0662:
0663:                    if (isDebug) {
0664:                        log("replyTo set to: " + replyTo);
0665:                    }
0666:                }
0667:            }
0668:
0669:            /**
0670:             * Gets the <CODE>reversePath</CODE> property.
0671:             * Returns the reverse-path of the new message,
0672:             * or null if no change is requested.
0673:             * Is a "getX()" method.
0674:             *
0675:             * @return the <CODE>reversePath</CODE> init parameter 
0676:             * or the postmaster address
0677:             * or <CODE>SpecialAddress.SENDER</CODE>
0678:             * or <CODE>SpecialAddress.NULL</CODE>
0679:             * or <CODE>SpecialAddress.UNALTERED</CODE>
0680:             * or <CODE>null</CODE> if missing
0681:             */
0682:            protected MailAddress getReversePath() throws MessagingException {
0683:                String addressString = getInitParameter("reversePath");
0684:                if (addressString != null) {
0685:                    MailAddress specialAddress = getSpecialAddress(
0686:                            addressString, new String[] { "postmaster",
0687:                                    "sender", "null", "unaltered" });
0688:                    if (specialAddress != null) {
0689:                        return specialAddress;
0690:                    }
0691:
0692:                    try {
0693:                        return new MailAddress(addressString);
0694:                    } catch (Exception e) {
0695:                        throw new MessagingException(
0696:                                "Exception thrown in getReversePath() parsing: "
0697:                                        + addressString, e);
0698:                    }
0699:                }
0700:
0701:                return null;
0702:            }
0703:
0704:            /**
0705:             * Gets the <CODE>reversePath</CODE> property,
0706:             * built dynamically using the original Mail object.
0707:             * Is a "getX(Mail)" method.
0708:             *
0709:             * @return {@link #getReversePath()},
0710:             * replacing <CODE>SpecialAddress.SENDER</CODE> if applicable with null,
0711:             * replacing <CODE>SpecialAddress.UNALTERED</CODE>
0712:             * and <CODE>SpecialAddress.REVERSE_PATH</CODE> if applicable with null,
0713:             * but not replacing <CODE>SpecialAddress.NULL</CODE>
0714:             * that will be handled by {@link #setReversePath}
0715:             */
0716:            protected MailAddress getReversePath(Mail originalMail)
0717:                    throws MessagingException {
0718:                MailAddress reversePath = (isStatic()) ? this .reversePath
0719:                        : getReversePath();
0720:                if (reversePath != null) {
0721:                    if (reversePath == SpecialAddress.UNALTERED
0722:                            || reversePath == SpecialAddress.REVERSE_PATH) {
0723:                        reversePath = null;
0724:                    } else if (reversePath == SpecialAddress.SENDER) {
0725:                        reversePath = null;
0726:                    }
0727:                }
0728:                return reversePath;
0729:            }
0730:
0731:            /**
0732:             * Sets the "reverse-path" of <I>newMail</I> to <I>reversePath</I>.
0733:             * If the requested value is <CODE>SpecialAddress.NULL</CODE> sets it to "<>".
0734:             * If the requested value is null does nothing.
0735:             * Is a "setX(Mail, Tx, Mail)" method.
0736:             */
0737:            protected void setReversePath(MailImpl newMail,
0738:                    MailAddress reversePath, Mail originalMail)
0739:                    throws MessagingException {
0740:                if (reversePath != null) {
0741:                    if (reversePath == SpecialAddress.NULL) {
0742:                        reversePath = null;
0743:                    }
0744:                    newMail.setSender(reversePath);
0745:                    if (isDebug) {
0746:                        log("reversePath set to: " + reversePath);
0747:                    }
0748:                }
0749:            }
0750:
0751:            /**
0752:             * Gets the <CODE>sender</CODE> property.
0753:             * Returns the new sender as a MailAddress,
0754:             * or null if no change is requested.
0755:             * Is a "getX()" method.
0756:             *
0757:             * @return the <CODE>sender</CODE> init parameter
0758:             * or the postmaster address
0759:             * or <CODE>SpecialAddress.SENDER</CODE>
0760:             * or <CODE>SpecialAddress.UNALTERED</CODE>
0761:             * or <CODE>null</CODE> if missing
0762:             */
0763:            protected MailAddress getSender() throws MessagingException {
0764:                String addressString = getInitParameter("sender");
0765:                if (addressString != null) {
0766:                    MailAddress specialAddress = getSpecialAddress(
0767:                            addressString, new String[] { "postmaster",
0768:                                    "sender", "unaltered" });
0769:                    if (specialAddress != null) {
0770:                        return specialAddress;
0771:                    }
0772:
0773:                    try {
0774:                        return new MailAddress(addressString);
0775:                    } catch (Exception e) {
0776:                        throw new MessagingException(
0777:                                "Exception thrown in getSender() parsing: "
0778:                                        + addressString, e);
0779:                    }
0780:                }
0781:
0782:                return null;
0783:            }
0784:
0785:            /**
0786:             * Gets the <CODE>sender</CODE> property,
0787:             * built dynamically using the original Mail object.
0788:             * Is a "getX(Mail)" method.
0789:             *
0790:             * @return {@link #getSender()}
0791:             * replacing <CODE>SpecialAddress.UNALTERED</CODE>
0792:             * and <CODE>SpecialAddress.SENDER</CODE> if applicable with null
0793:             */
0794:            protected MailAddress getSender(Mail originalMail)
0795:                    throws MessagingException {
0796:                MailAddress sender = (isStatic()) ? this .sender : getSender();
0797:                if (sender != null) {
0798:                    if (sender == SpecialAddress.UNALTERED
0799:                            || sender == SpecialAddress.SENDER) {
0800:                        sender = null;
0801:                    }
0802:                }
0803:                return sender;
0804:            }
0805:
0806:            /**
0807:             * Sets the "From:" header of <I>newMail</I> to <I>sender</I>.
0808:             * If the requested value is null does nothing.
0809:             * Is a "setX(Mail, Tx, Mail)" method.
0810:             */
0811:            protected void setSender(Mail newMail, MailAddress sender,
0812:                    Mail originalMail) throws MessagingException {
0813:                if (sender != null) {
0814:                    newMail.getMessage().setFrom(sender.toInternetAddress());
0815:
0816:                    if (isDebug) {
0817:                        log("sender set to: " + sender);
0818:                    }
0819:                }
0820:            }
0821:
0822:            /**
0823:             * Gets the <CODE>subject</CODE> property.
0824:             * Returns a string for the new message subject.
0825:             * Is a "getX()" method.
0826:             *
0827:             * @return the <CODE>subject</CODE> init parameter or null if missing
0828:             */
0829:            protected String getSubject() throws MessagingException {
0830:                return getInitParameter("subject");
0831:            }
0832:
0833:            /**
0834:             * Gets the <CODE>subject</CODE> property,
0835:             * built dynamically using the original Mail object.
0836:             * Is a "getX(Mail)" method.
0837:             *
0838:             * @return {@link #getSubject()}
0839:             */
0840:            protected String getSubject(Mail originalMail)
0841:                    throws MessagingException {
0842:                return (isStatic()) ? this .subject : getSubject();
0843:            }
0844:
0845:            /**
0846:             * Gets the <CODE>prefix</CODE> property.
0847:             * Returns a prefix for the new message subject.
0848:             * Is a "getX()" method.
0849:             *
0850:             * @return the <CODE>prefix</CODE> init parameter or an empty string if missing
0851:             */
0852:            protected String getSubjectPrefix() throws MessagingException {
0853:                return getInitParameter("prefix");
0854:            }
0855:
0856:            /**
0857:             * Gets the <CODE>subjectPrefix</CODE> property,
0858:             * built dynamically using the original Mail object.
0859:             * Is a "getX(Mail)" method.
0860:             *
0861:             * @return {@link #getSubjectPrefix()}
0862:             */
0863:            protected String getSubjectPrefix(Mail originalMail)
0864:                    throws MessagingException {
0865:                return (isStatic()) ? this .subjectPrefix : getSubjectPrefix();
0866:            }
0867:
0868:            /**
0869:             * Builds the subject of <I>newMail</I> appending the subject
0870:             * of <I>originalMail</I> to <I>subjectPrefix</I>.
0871:             * Is a "setX(Mail, Tx, Mail)" method.
0872:             */
0873:            protected void setSubjectPrefix(Mail newMail, String subjectPrefix,
0874:                    Mail originalMail) throws MessagingException {
0875:                String subject = getSubject(originalMail);
0876:                if ((subjectPrefix != null && subjectPrefix.length() > 0)
0877:                        || subject != null) {
0878:                    if (subject == null) {
0879:                        subject = originalMail.getMessage().getSubject();
0880:                    } else {
0881:                        // replacing the subject
0882:                        if (isDebug) {
0883:                            log("subject set to: " + subject);
0884:                        }
0885:                    }
0886:                    // Was null in original?
0887:                    if (subject == null) {
0888:                        subject = "";
0889:                    }
0890:
0891:                    if (subjectPrefix != null) {
0892:                        subject = subjectPrefix + subject;
0893:                        // adding a prefix
0894:                        if (isDebug) {
0895:                            log("subjectPrefix set to: " + subjectPrefix);
0896:                        }
0897:                    }
0898:                    //            newMail.getMessage().setSubject(subject);
0899:                    changeSubject(newMail.getMessage(), subject);
0900:                }
0901:            }
0902:
0903:            /**
0904:             * Gets the <CODE>attachError</CODE> property.
0905:             * Returns a boolean indicating whether to append a description of any error to the main body part
0906:             * of the new message, if getInlineType does not return "UNALTERED".
0907:             * Is a "getX()" method.
0908:             *
0909:             * @return the <CODE>attachError</CODE> init parameter; false if missing
0910:             */
0911:            protected boolean attachError() throws MessagingException {
0912:                return new Boolean(getInitParameter("attachError"))
0913:                        .booleanValue();
0914:            }
0915:
0916:            /**
0917:             * Gets the <CODE>attachError</CODE> property,
0918:             * built dynamically using the original Mail object.
0919:             * Is a "getX(Mail)" method.
0920:             *
0921:             * @return {@link #attachError()}
0922:             */
0923:            protected boolean attachError(Mail originalMail)
0924:                    throws MessagingException {
0925:                return (isStatic()) ? this .attachError : attachError();
0926:            }
0927:
0928:            /**
0929:             * Gets the <CODE>isReply</CODE> property.
0930:             * Returns a boolean indicating whether the new message must be considered
0931:             * a reply to the original message, setting the IN_REPLY_TO header of the new
0932:             * message to the id of the original message.
0933:             * Is a "getX()" method.
0934:             *
0935:             * @return the <CODE>isReply</CODE> init parameter; false if missing
0936:             */
0937:            protected boolean isReply() throws MessagingException {
0938:                return new Boolean(getInitParameter("isReply")).booleanValue();
0939:            }
0940:
0941:            /**
0942:             * Gets the <CODE>isReply</CODE> property,
0943:             * built dynamically using the original Mail object.
0944:             * Is a "getX(Mail)" method.
0945:             *
0946:             * @return {@link #isReply()}
0947:             */
0948:            protected boolean isReply(Mail originalMail)
0949:                    throws MessagingException {
0950:                return (isStatic()) ? this .isReply : isReply();
0951:            }
0952:
0953:            /**
0954:             * Sets the "In-Reply-To:" header of <I>newMail</I> to the "Message-Id:" of
0955:             * <I>originalMail</I>, if <I>isReply</I> is true.
0956:             */
0957:            protected void setIsReply(Mail newMail, boolean isReply,
0958:                    Mail originalMail) throws MessagingException {
0959:                if (isReply) {
0960:                    String messageId = originalMail.getMessage().getMessageID();
0961:                    if (messageId != null) {
0962:                        newMail.getMessage().setHeader(
0963:                                RFC2822Headers.IN_REPLY_TO, messageId);
0964:                        if (isDebug) {
0965:                            log("IN_REPLY_TO set to: " + messageId);
0966:                        }
0967:                    }
0968:                }
0969:            }
0970:
0971:            /* ******************************************************************** */
0972:            /* ******************* End of getX and setX methods ******************* */
0973:            /* ******************************************************************** */
0974:
0975:            /**
0976:             * Mailet initialization routine.
0977:             * Will setup static values for each "x" initialization parameter in config.xml,
0978:             * using getX(), if {@link #isStatic()} returns true.
0979:             */
0980:            public void init() throws MessagingException {
0981:                isDebug = new Boolean(getInitParameter("debug", "false"))
0982:                        .booleanValue();
0983:
0984:                isStatic = new Boolean(getInitParameter("static", "false"))
0985:                        .booleanValue();
0986:
0987:                if (isDebug) {
0988:                    log("Initializing");
0989:                }
0990:
0991:                // check that all init parameters have been declared in allowedInitParameters
0992:                checkInitParameters(getAllowedInitParameters());
0993:
0994:                if (isStatic()) {
0995:                    passThrough = getPassThrough();
0996:                    fakeDomainCheck = getFakeDomainCheck();
0997:                    attachmentType = getAttachmentType();
0998:                    inLineType = getInLineType();
0999:                    messageText = getMessage();
1000:                    recipients = getRecipients();
1001:                    replyTo = getReplyTo();
1002:                    reversePath = getReversePath();
1003:                    sender = getSender();
1004:                    subject = getSubject();
1005:                    subjectPrefix = getSubjectPrefix();
1006:                    apparentlyTo = getTo();
1007:                    attachError = attachError();
1008:                    isReply = isReply();
1009:                    if (isDebug) {
1010:                        StringBuffer logBuffer = new StringBuffer(1024).append(
1011:                                "static").append(", passThrough=").append(
1012:                                passThrough).append(", fakeDomainCheck=")
1013:                                .append(fakeDomainCheck).append(", sender=")
1014:                                .append(sender).append(", replyTo=").append(
1015:                                        replyTo).append(", reversePath=")
1016:                                .append(reversePath).append(", message=")
1017:                                .append(messageText).append(", recipients=")
1018:                                .append(
1019:                                        arrayToString(recipients == null ? null
1020:                                                : recipients.toArray()))
1021:                                .append(", subject=").append(subject).append(
1022:                                        ", subjectPrefix=").append(
1023:                                        subjectPrefix)
1024:                                .append(", apparentlyTo=").append(
1025:                                        arrayToString(apparentlyTo)).append(
1026:                                        ", attachError=").append(attachError)
1027:                                .append(", isReply=").append(isReply).append(
1028:                                        ", attachmentType=").append(
1029:                                        attachmentType).append(", inLineType=")
1030:                                .append(inLineType).append(" ");
1031:                        log(logBuffer.toString());
1032:                    }
1033:                }
1034:            }
1035:
1036:            /**
1037:             * Service does the hard work,and redirects the originalMail in the form specified.
1038:             *
1039:             * @param originalMail the mail to process and redirect
1040:             * @throws MessagingException if a problem arises formulating the redirected mail
1041:             */
1042:            public void service(Mail originalMail) throws MessagingException {
1043:
1044:                boolean keepMessageId = false;
1045:
1046:                // duplicates the Mail object, to be able to modify the new mail keeping the original untouched
1047:                MailImpl newMail = new MailImpl(originalMail,
1048:                        newName(originalMail));
1049:                try {
1050:                    // We don't need to use the original Remote Address and Host,
1051:                    // and doing so would likely cause a loop with spam detecting
1052:                    // matchers.
1053:                    try {
1054:                        newMail.setRemoteAddr(java.net.InetAddress
1055:                                .getLocalHost().getHostAddress());
1056:                        newMail.setRemoteHost(java.net.InetAddress
1057:                                .getLocalHost().getHostName());
1058:                    } catch (java.net.UnknownHostException _) {
1059:                        newMail.setRemoteAddr("127.0.0.1");
1060:                        newMail.setRemoteHost("localhost");
1061:                    }
1062:
1063:                    if (isDebug) {
1064:                        log("New mail - sender: "
1065:                                + newMail.getSender()
1066:                                + ", recipients: "
1067:                                + arrayToString(newMail.getRecipients()
1068:                                        .toArray()) + ", name: "
1069:                                + newMail.getName() + ", remoteHost: "
1070:                                + newMail.getRemoteHost() + ", remoteAddr: "
1071:                                + newMail.getRemoteAddr() + ", state: "
1072:                                + newMail.getState() + ", lastUpdated: "
1073:                                + newMail.getLastUpdated() + ", errorMessage: "
1074:                                + newMail.getErrorMessage());
1075:                    }
1076:
1077:                    //Create the message
1078:                    if (getInLineType(originalMail) != UNALTERED) {
1079:                        if (isDebug) {
1080:                            log("Alter message");
1081:                        }
1082:                        newMail.setMessage(new MimeMessage(Session
1083:                                .getDefaultInstance(System.getProperties(),
1084:                                        null)));
1085:
1086:                        // handle the new message if altered
1087:                        buildAlteredMessage(newMail, originalMail);
1088:
1089:                    } else {
1090:                        // if we need the original, create a copy of this message to redirect
1091:                        if (getPassThrough(originalMail)) {
1092:                            newMail.setMessage(new MimeMessage(originalMail
1093:                                    .getMessage()) {
1094:                                protected void updateHeaders()
1095:                                        throws MessagingException {
1096:                                    if (getMessageID() == null)
1097:                                        super .updateHeaders();
1098:                                    else {
1099:                                        modified = false;
1100:                                    }
1101:                                }
1102:                            });
1103:                        }
1104:                        if (isDebug) {
1105:                            log("Message resent unaltered.");
1106:                        }
1107:                        keepMessageId = true;
1108:                    }
1109:
1110:                    //Set additional headers
1111:
1112:                    setRecipients(newMail, getRecipients(originalMail),
1113:                            originalMail);
1114:
1115:                    setTo(newMail, getTo(originalMail), originalMail);
1116:
1117:                    setSubjectPrefix(newMail, getSubjectPrefix(originalMail),
1118:                            originalMail);
1119:
1120:                    if (newMail.getMessage().getHeader(RFC2822Headers.DATE) == null) {
1121:                        newMail.getMessage().setHeader(RFC2822Headers.DATE,
1122:                                rfc822DateFormat.format(new Date()));
1123:                    }
1124:
1125:                    setReplyTo(newMail, getReplyTo(originalMail), originalMail);
1126:
1127:                    setReversePath(newMail, getReversePath(originalMail),
1128:                            originalMail);
1129:
1130:                    setSender(newMail, getSender(originalMail), originalMail);
1131:
1132:                    setIsReply(newMail, isReply(originalMail), originalMail);
1133:
1134:                    newMail.getMessage().saveChanges();
1135:
1136:                    if (keepMessageId) {
1137:                        setMessageId(newMail, originalMail);
1138:                    }
1139:
1140:                    if (senderDomainIsValid(newMail)) {
1141:                        //Send it off...
1142:                        getMailetContext().sendMail(newMail);
1143:                    } else {
1144:                        StringBuffer logBuffer = new StringBuffer(256).append(
1145:                                getMailetName()).append(
1146:                                " mailet cannot forward ").append(
1147:                                originalMail.getName()).append(
1148:                                ". Invalid sender domain for ").append(
1149:                                newMail.getSender()).append(
1150:                                ". Consider using the Resend mailet ").append(
1151:                                "using a different sender.");
1152:                        throw new MessagingException(logBuffer.toString());
1153:                    }
1154:
1155:                } finally {
1156:                    newMail.dispose();
1157:                }
1158:
1159:                if (!getPassThrough(originalMail)) {
1160:                    originalMail.setState(Mail.GHOST);
1161:                }
1162:            }
1163:
1164:            private static final java.util.Random random = new java.util.Random(); // Used to generate new mail names
1165:
1166:            /**
1167:             * Create a unique new primary key name.
1168:             *
1169:             * @param mail the mail to use as the basis for the new mail name
1170:             * @return a new name
1171:             */
1172:            private String newName(Mail mail) throws MessagingException {
1173:                String oldName = mail.getName();
1174:
1175:                // Checking if the original mail name is too long, perhaps because of a
1176:                // loop caused by a configuration error.
1177:                // it could cause a "null pointer exception" in AvalonMailRepository much
1178:                // harder to understand.
1179:                if (oldName.length() > 76) {
1180:                    int count = 0;
1181:                    int index = 0;
1182:                    while ((index = oldName.indexOf('!', index + 1)) >= 0) {
1183:                        count++;
1184:                    }
1185:                    // It looks like a configuration loop. It's better to stop.
1186:                    if (count > 7) {
1187:                        throw new MessagingException(
1188:                                "Unable to create a new message name: too long."
1189:                                        + " Possible loop in config.xml.");
1190:                    } else {
1191:                        oldName = oldName.substring(0, 76);
1192:                    }
1193:                }
1194:
1195:                StringBuffer nameBuffer = new StringBuffer(64).append(oldName)
1196:                        .append("-!").append(random.nextInt(1048576));
1197:                return nameBuffer.toString();
1198:            }
1199:
1200:            /**
1201:             * A private method to convert types from string to int.
1202:             *
1203:             * @param param the string type
1204:             * @return the corresponding int enumeration
1205:             */
1206:            protected int getTypeCode(String param) {
1207:                param = param.toLowerCase(Locale.US);
1208:                if (param.compareTo("unaltered") == 0) {
1209:                    return UNALTERED;
1210:                }
1211:                if (param.compareTo("heads") == 0) {
1212:                    return HEADS;
1213:                }
1214:                if (param.compareTo("body") == 0) {
1215:                    return BODY;
1216:                }
1217:                if (param.compareTo("all") == 0) {
1218:                    return ALL;
1219:                }
1220:                if (param.compareTo("none") == 0) {
1221:                    return NONE;
1222:                }
1223:                if (param.compareTo("message") == 0) {
1224:                    return MESSAGE;
1225:                }
1226:                return NONE;
1227:            }
1228:
1229:            /**
1230:             * Utility method for obtaining a string representation of an array of Objects.
1231:             */
1232:            private String arrayToString(Object[] array) {
1233:                if (array == null) {
1234:                    return "null";
1235:                }
1236:                StringBuffer sb = new StringBuffer(1024);
1237:                sb.append("[");
1238:                for (int i = 0; i < array.length; i++) {
1239:                    if (i > 0) {
1240:                        sb.append(",");
1241:                    }
1242:                    sb.append(array[i]);
1243:                }
1244:                sb.append("]");
1245:                return sb.toString();
1246:            }
1247:
1248:            /**
1249:             * Utility method for obtaining a string representation of a
1250:             * Message's headers
1251:             */
1252:            protected String getMessageHeaders(MimeMessage message)
1253:                    throws MessagingException {
1254:                Enumeration heads = message.getAllHeaderLines();
1255:                StringBuffer headBuffer = new StringBuffer(1024);
1256:                while (heads.hasMoreElements()) {
1257:                    headBuffer.append(heads.nextElement().toString()).append(
1258:                            "\r\n");
1259:                }
1260:                return headBuffer.toString();
1261:            }
1262:
1263:            /**
1264:             * Utility method for obtaining a string representation of a
1265:             * Message's body
1266:             */
1267:            private String getMessageBody(MimeMessage message) throws Exception {
1268:                java.io.ByteArrayOutputStream bodyOs = new java.io.ByteArrayOutputStream();
1269:                MimeMessageUtil.writeMessageBodyTo(message, bodyOs);
1270:                return bodyOs.toString();
1271:            }
1272:
1273:            /**
1274:             * Builds the message of the newMail in case it has to be altered.
1275:             *
1276:             * @param originalMail the original Mail object
1277:             * @param newMail the Mail object to build
1278:             */
1279:            protected void buildAlteredMessage(Mail newMail, Mail originalMail)
1280:                    throws MessagingException {
1281:
1282:                MimeMessage originalMessage = originalMail.getMessage();
1283:                MimeMessage newMessage = newMail.getMessage();
1284:
1285:                // Copy the relevant headers
1286:                String[] relevantHeaderNames = { RFC2822Headers.DATE,
1287:                        RFC2822Headers.FROM, RFC2822Headers.REPLY_TO,
1288:                        RFC2822Headers.TO, RFC2822Headers.SUBJECT,
1289:                        RFC2822Headers.RETURN_PATH };
1290:                Enumeration headerEnum = originalMessage
1291:                        .getMatchingHeaderLines(relevantHeaderNames);
1292:                while (headerEnum.hasMoreElements()) {
1293:                    newMessage.addHeaderLine((String) headerEnum.nextElement());
1294:                }
1295:
1296:                StringWriter sout = new StringWriter();
1297:                PrintWriter out = new PrintWriter(sout, true);
1298:                String head = getMessageHeaders(originalMessage);
1299:                boolean all = false;
1300:
1301:                String messageText = getMessage(originalMail);
1302:                if (messageText != null) {
1303:                    out.println(messageText);
1304:                }
1305:
1306:                if (isDebug) {
1307:                    log("inline:" + getInLineType(originalMail));
1308:                }
1309:                switch (getInLineType(originalMail)) {
1310:                case ALL: //ALL:
1311:                    all = true;
1312:                case HEADS: //HEADS:
1313:                    out.println("Message Headers:");
1314:                    out.println(head);
1315:                    if (!all) {
1316:                        break;
1317:                    }
1318:                case BODY: //BODY:
1319:                    out.println("Message:");
1320:                    try {
1321:                        out.println(getMessageBody(originalMessage));
1322:                    } catch (Exception e) {
1323:                        out.println("body unavailable");
1324:                    }
1325:                    break;
1326:                default:
1327:                case NONE: //NONE:
1328:                    break;
1329:                }
1330:
1331:                try {
1332:                    //Create the message body
1333:                    MimeMultipart multipart = new MimeMultipart("mixed");
1334:
1335:                    // Create the message
1336:                    MimeMultipart mpContent = new MimeMultipart("alternative");
1337:                    MimeBodyPart contentPartRoot = new MimeBodyPart();
1338:                    contentPartRoot.setContent(mpContent);
1339:
1340:                    multipart.addBodyPart(contentPartRoot);
1341:
1342:                    MimeBodyPart part = new MimeBodyPart();
1343:                    part.setText(sout.toString());
1344:                    part.setDisposition("inline");
1345:                    mpContent.addBodyPart(part);
1346:                    if (isDebug) {
1347:                        log("attachmentType:" + getAttachmentType(originalMail));
1348:                    }
1349:                    if (getAttachmentType(originalMail) != NONE) {
1350:                        part = new MimeBodyPart();
1351:                        switch (getAttachmentType(originalMail)) {
1352:                        case HEADS: //HEADS:
1353:                            part.setText(head);
1354:                            break;
1355:                        case BODY: //BODY:
1356:                            try {
1357:                                part.setText(getMessageBody(originalMessage));
1358:                            } catch (Exception e) {
1359:                                part.setText("body unavailable");
1360:                            }
1361:                            break;
1362:                        case ALL: //ALL:
1363:                            StringBuffer textBuffer = new StringBuffer(1024)
1364:                                    .append(head).append("\r\nMessage:\r\n")
1365:                                    .append(getMessageBody(originalMessage));
1366:                            part.setText(textBuffer.toString());
1367:                            break;
1368:                        case MESSAGE: //MESSAGE:
1369:                            part.setContent(originalMessage, "message/rfc822");
1370:                            break;
1371:                        }
1372:                        if ((originalMessage.getSubject() != null)
1373:                                && (originalMessage.getSubject().trim()
1374:                                        .length() > 0)) {
1375:                            part.setFileName(originalMessage.getSubject()
1376:                                    .trim());
1377:                        } else {
1378:                            part.setFileName("No Subject");
1379:                        }
1380:                        part.setDisposition("Attachment");
1381:                        multipart.addBodyPart(part);
1382:                    }
1383:                    //if set, attach the original mail's error message
1384:                    if (attachError(originalMail)
1385:                            && originalMail.getErrorMessage() != null) {
1386:                        part = new MimeBodyPart();
1387:                        part.setContent(originalMail.getErrorMessage(),
1388:                                "text/plain");
1389:                        part.setHeader(RFC2822Headers.CONTENT_TYPE,
1390:                                "text/plain");
1391:                        part.setFileName("Reasons");
1392:                        part.setDisposition(javax.mail.Part.ATTACHMENT);
1393:                        multipart.addBodyPart(part);
1394:                    }
1395:                    newMail.getMessage().setContent(multipart);
1396:                    newMail.getMessage().setHeader(RFC2822Headers.CONTENT_TYPE,
1397:                            multipart.getContentType());
1398:
1399:                } catch (Exception ioe) {
1400:                    throw new MessagingException(
1401:                            "Unable to create multipart body", ioe);
1402:                }
1403:            }
1404:
1405:            /**
1406:             * Sets the message id of originalMail into newMail.
1407:             */
1408:            private void setMessageId(Mail newMail, Mail originalMail)
1409:                    throws MessagingException {
1410:                String messageId = originalMail.getMessage().getMessageID();
1411:                if (messageId != null) {
1412:                    newMail.getMessage().setHeader(RFC2822Headers.MESSAGE_ID,
1413:                            messageId);
1414:                    if (isDebug) {
1415:                        log("MESSAGE_ID restored to: " + messageId);
1416:                    }
1417:                }
1418:            }
1419:
1420:            /**
1421:             * Returns the {@link SpecialAddress} that corresponds to an init parameter value.
1422:             * The init parameter value is checked against a String[] of allowed values.
1423:             * The checks are case insensitive.
1424:             *
1425:             * @param addressString the string to check if is a special address
1426:             * @param allowedSpecials a String[] with the allowed special addresses
1427:             * @return a SpecialAddress if found, null if not found or addressString is null
1428:             * @throws MessagingException if is a special address not in the allowedSpecials array
1429:             */
1430:            protected final MailAddress getSpecialAddress(String addressString,
1431:                    String[] allowedSpecials) throws MessagingException {
1432:                if (addressString == null) {
1433:                    return null;
1434:                }
1435:
1436:                addressString = addressString.toLowerCase(Locale.US);
1437:                addressString = addressString.trim();
1438:
1439:                MailAddress specialAddress = null;
1440:
1441:                if (addressString.compareTo("postmaster") == 0) {
1442:                    specialAddress = getMailetContext().getPostmaster();
1443:                }
1444:                if (addressString.compareTo("sender") == 0) {
1445:                    specialAddress = SpecialAddress.SENDER;
1446:                }
1447:                if (addressString.compareTo("reversepath") == 0) {
1448:                    specialAddress = SpecialAddress.REVERSE_PATH;
1449:                }
1450:                if (addressString.compareTo("from") == 0) {
1451:                    specialAddress = SpecialAddress.FROM;
1452:                }
1453:                if (addressString.compareTo("replyto") == 0) {
1454:                    specialAddress = SpecialAddress.REPLY_TO;
1455:                }
1456:                if (addressString.compareTo("to") == 0) {
1457:                    specialAddress = SpecialAddress.TO;
1458:                }
1459:                if (addressString.compareTo("recipients") == 0) {
1460:                    specialAddress = SpecialAddress.RECIPIENTS;
1461:                }
1462:                if (addressString.compareTo("delete") == 0) {
1463:                    specialAddress = SpecialAddress.DELETE;
1464:                }
1465:                if (addressString.compareTo("unaltered") == 0) {
1466:                    specialAddress = SpecialAddress.UNALTERED;
1467:                }
1468:                if (addressString.compareTo("null") == 0) {
1469:                    specialAddress = SpecialAddress.NULL;
1470:                }
1471:
1472:                // if is a special address, must be in the allowedSpecials array
1473:                if (specialAddress != null) {
1474:                    // check if is an allowed special
1475:                    boolean allowed = false;
1476:                    for (int i = 0; i < allowedSpecials.length; i++) {
1477:                        String allowedSpecial = allowedSpecials[i];
1478:                        allowedSpecial = allowedSpecial.toLowerCase(Locale.US);
1479:                        allowedSpecial = allowedSpecial.trim();
1480:                        if (addressString.compareTo(allowedSpecial) == 0) {
1481:                            allowed = true;
1482:                            break;
1483:                        }
1484:                    }
1485:                    if (!allowed) {
1486:                        throw new MessagingException(
1487:                                "Special (\"magic\") address found not allowed: "
1488:                                        + addressString
1489:                                        + ", allowed values are \""
1490:                                        + arrayToString(allowedSpecials) + "\"");
1491:                    }
1492:                }
1493:
1494:                return specialAddress;
1495:            }
1496:
1497:            /**
1498:             * <P>Checks if a sender domain of <I>mail</I> is valid.</P>
1499:             * <P>If we do not do this check, and someone uses a redirection mailet in a
1500:             * processor initiated by SenderInFakeDomain, then a fake
1501:             * sender domain will cause an infinite loop (the forwarded
1502:             * e-mail still appears to come from a fake domain).<BR>
1503:             * Although this can be viewed as a configuration error, the
1504:             * consequences of such a mis-configuration are severe enough
1505:             * to warrant protecting against the infinite loop.</P>
1506:             * <P>This check can be skipped if {@link #getFakeDomainCheck(Mail)} returns true.</P> 
1507:             *
1508:             * @param mail the mail object to check
1509:             * @return true if the if the sender is null or
1510:             * {@link org.apache.mailet.MailetContext#getMailServers} returns true for
1511:             * the sender host part
1512:             */
1513:            protected final boolean senderDomainIsValid(Mail mail)
1514:                    throws MessagingException {
1515:                if (getFakeDomainCheck(mail)) {
1516:                    return mail.getSender() == null
1517:                            || getMailetContext().getMailServers(
1518:                                    mail.getSender().getHost()).size() != 0;
1519:                } else
1520:                    return true;
1521:            }
1522:
1523:            /**
1524:             * Checks if there are unallowed init parameters specified in the configuration file
1525:             * against the String[] allowedInitParameters.
1526:             */
1527:            private void checkInitParameters(String[] allowedArray)
1528:                    throws MessagingException {
1529:                // if null then no check is requested
1530:                if (allowedArray == null) {
1531:                    return;
1532:                }
1533:
1534:                Collection allowed = new HashSet();
1535:                Collection bad = new ArrayList();
1536:
1537:                for (int i = 0; i < allowedArray.length; i++) {
1538:                    allowed.add(allowedArray[i]);
1539:                }
1540:
1541:                Iterator iterator = getInitParameterNames();
1542:                while (iterator.hasNext()) {
1543:                    String parameter = (String) iterator.next();
1544:                    if (!allowed.contains(parameter)) {
1545:                        bad.add(parameter);
1546:                    }
1547:                }
1548:
1549:                if (bad.size() > 0) {
1550:                    throw new MessagingException(
1551:                            "Unexpected init parameters found: "
1552:                                    + arrayToString(bad.toArray()));
1553:                }
1554:            }
1555:
1556:            /**
1557:             * It changes the subject of the supplied message to to supplied value 
1558:             * but it also tries to preserve the original charset information.<BR>
1559:             * 
1560:             * This method was needed to avoid sending the subject using a charset
1561:             * (usually the default charset on the server) which doesn't contain
1562:             * the characters in the subject, resulting in the loss of these characters. 
1563:             * The most simple method would be to either send it in ASCII unencoded 
1564:             * or in UTF-8 if non-ASCII characters are present but unfortunately UTF-8 
1565:             * is not yet a MIME standard and not all email clients 
1566:             * are supporting it. The optimal method would be to determine the best 
1567:             * charset by analyzing the actual characters. That would require much 
1568:             * more work (exept if an open source library already exists for this). 
1569:             * However there is nothing to stop somebody to add a detection algorithm
1570:             * for a specific charset. <BR>
1571:             * 
1572:             * The current algorithm works correctly if only ASCII characters are 
1573:             * added to an existing subject.<BR>
1574:             * 
1575:             * If the new value is ASCII only, then it doesn't apply any encoding to
1576:             * the subject header. (This is provided by MimeMessage.setSubject()).<BR>
1577:             * 
1578:             * Possible enhancement:  under java 1.4 java.nio the system can determine if the
1579:             * suggested charset fits or not (if there is untranslatable
1580:             * characters). If the charset doesn't fit the new value, it
1581:             * can fall back to UTF-8.<BR>
1582:             * 
1583:             * @param message the message of which subject is changed 
1584:             * @param newValue the new (unencoded) value of the subject. It must
1585:             *   not be null.
1586:             * @throws MessagingException - according to the JavaMail doc most likely
1587:             *    this is never thrown
1588:             */
1589:            public static void changeSubject(MimeMessage message,
1590:                    String newValue) throws MessagingException {
1591:                String rawSubject = message.getHeader(RFC2822Headers.SUBJECT,
1592:                        null);
1593:                String mimeCharset = determineMailHeaderEncodingCharset(rawSubject);
1594:                if (mimeCharset == null) { // most likely ASCII
1595:                    // it uses the system charset or the value of the
1596:                    // mail.mime.charset property if set  
1597:                    message.setSubject(newValue);
1598:                    return;
1599:                } else { // original charset determined 
1600:                    String javaCharset = javax.mail.internet.MimeUtility
1601:                            .javaCharset(mimeCharset);
1602:                    try {
1603:                        message.setSubject(newValue, javaCharset);
1604:                    } catch (MessagingException e) {
1605:                        // known, but unsupported encoding
1606:                        // this should be logged, the admin may setup a more i18n
1607:                        // capable JRE, but the log API cannot be accessed from here  
1608:                        //if (charset != null) log(charset + 
1609:                        //      " charset unsupported by the JRE, email subject may be damaged");
1610:                        message.setSubject(newValue); // recover
1611:                    }
1612:                }
1613:            }
1614:
1615:            /**
1616:             * It attempts to determine the charset used to encode an "unstructured" 
1617:             * RFC 822 header (like Subject). The encoding is specified in RFC 2047.
1618:             * If it cannot determine or the the text is not encoded then it returns null.
1619:             *
1620:             * Here is an example raw text: 
1621:             * Subject: =?iso-8859-2?Q?leg=FAjabb_pr=F3ba_l=F5elemmel?=
1622:             *
1623:             * @param rawText the raw (not decoded) value of the header. Null means
1624:             *   that the header was not present (in this case it always return null).
1625:             * @return the MIME charset name or null if no encoding applied
1626:             */
1627:            static private String determineMailHeaderEncodingCharset(
1628:                    String rawText) {
1629:                if (rawText == null)
1630:                    return null;
1631:                int iEncodingPrefix = rawText.indexOf("=?");
1632:                if (iEncodingPrefix == -1)
1633:                    return null;
1634:                int iCharsetBegin = iEncodingPrefix + 2;
1635:                int iSecondQuestionMark = rawText.indexOf('?', iCharsetBegin);
1636:                if (iSecondQuestionMark == -1)
1637:                    return null;
1638:                // safety checks
1639:                if (iSecondQuestionMark == iCharsetBegin)
1640:                    return null; // empty charset? impossible
1641:                int iThirdQuestionMark = rawText.indexOf('?',
1642:                        iSecondQuestionMark + 1);
1643:                if (iThirdQuestionMark == -1)
1644:                    return null; // there must be one after encoding
1645:                if (-1 == rawText.indexOf("?=", iThirdQuestionMark + 1))
1646:                    return null; // closing tag
1647:                String mimeCharset = rawText.substring(iCharsetBegin,
1648:                        iSecondQuestionMark);
1649:                return mimeCharset;
1650:            }
1651:
1652:            /**
1653:             * Returns a new Collection built over <I>list</I> replacing special addresses
1654:             * with real <CODE>MailAddress</CODE>-es.<BR>
1655:             * Manages <CODE>SpecialAddress.SENDER</CODE>, <CODE>SpecialAddress.REVERSE_PATH</CODE>,
1656:             * <CODE>SpecialAddress.FROM</CODE>, <CODE>SpecialAddress.REPLY_TO</CODE>, 
1657:             * <CODE>SpecialAddress.RECIPIENTS</CODE>, <CODE>SpecialAddress.TO</CODE>, 
1658:             * <CODE>SpecialAddress.NULL</CODE> and <CODE>SpecialAddress.UNALTERED</CODE>.<BR>
1659:             * <CODE>SpecialAddress.FROM</CODE> is made equivalent to <CODE>SpecialAddress.SENDER</CODE>;
1660:             * <CODE>SpecialAddress.TO</CODE> is made equivalent to <CODE>SpecialAddress.RECIPIENTS</CODE>.<BR>
1661:             * <CODE>SpecialAddress.REPLY_TO</CODE> uses the ReplyTo header if available, otherwise the
1662:             * From header if available, otherwise the Sender header if available, otherwise the return-path.<BR>
1663:             * <CODE>SpecialAddress.NULL</CODE> and <CODE>SpecialAddress.UNALTERED</CODE> are ignored.<BR>
1664:             * Any other address is not replaced.
1665:             */
1666:            protected Collection replaceMailAddresses(Mail mail, Collection list) {
1667:                Collection newList = new HashSet(list.size());
1668:                Iterator iterator = list.iterator();
1669:                while (iterator.hasNext()) {
1670:                    MailAddress mailAddress = (MailAddress) iterator.next();
1671:                    if (!mailAddress.getHost().equalsIgnoreCase(
1672:                            "address.marker")) {
1673:                        newList.add(mailAddress);
1674:                    } else if (mailAddress == SpecialAddress.SENDER
1675:                            || mailAddress == SpecialAddress.FROM) {
1676:                        MailAddress sender = mail.getSender();
1677:                        if (sender != null) {
1678:                            newList.add(sender);
1679:                        }
1680:                    } else if (mailAddress == SpecialAddress.REPLY_TO) {
1681:                        int parsedAddressCount = 0;
1682:                        try {
1683:                            InternetAddress[] replyToArray = (InternetAddress[]) mail
1684:                                    .getMessage().getReplyTo();
1685:                            if (replyToArray != null) {
1686:                                for (int i = 0; i < replyToArray.length; i++) {
1687:                                    try {
1688:                                        newList.add(new MailAddress(
1689:                                                replyToArray[i]));
1690:                                        parsedAddressCount++;
1691:                                    } catch (ParseException pe) {
1692:                                        log("Unable to parse a \"REPLY_TO\" header address in the original message: "
1693:                                                + replyToArray[i]
1694:                                                + "; ignoring.");
1695:                                    }
1696:                                }
1697:                            }
1698:                        } catch (MessagingException ae) {
1699:                            log("Unable to parse the \"REPLY_TO\" header in the original message; ignoring.");
1700:                        }
1701:                        // no address was parsed?
1702:                        if (parsedAddressCount == 0) {
1703:                            MailAddress sender = mail.getSender();
1704:                            if (sender != null) {
1705:                                newList.add(sender);
1706:                            }
1707:                        }
1708:                    } else if (mailAddress == SpecialAddress.REVERSE_PATH) {
1709:                        MailAddress reversePath = mail.getSender();
1710:                        if (reversePath != null) {
1711:                            newList.add(reversePath);
1712:                        }
1713:                    } else if (mailAddress == SpecialAddress.RECIPIENTS
1714:                            || mailAddress == SpecialAddress.TO) {
1715:                        newList.addAll(mail.getRecipients());
1716:                    } else if (mailAddress == SpecialAddress.UNALTERED) {
1717:                        continue;
1718:                    } else if (mailAddress == SpecialAddress.NULL) {
1719:                        continue;
1720:                    } else {
1721:                        newList.add(mailAddress);
1722:                    }
1723:                }
1724:                return newList;
1725:            }
1726:
1727:            /**
1728:             * Returns a new Collection built over <I>list</I> replacing special addresses
1729:             * with real <CODE>InternetAddress</CODE>-es.<BR>
1730:             * Manages <CODE>SpecialAddress.SENDER</CODE>, <CODE>SpecialAddress.REVERSE_PATH</CODE>,
1731:             * <CODE>SpecialAddress.FROM</CODE>, <CODE>SpecialAddress.REPLY_TO</CODE>,
1732:             * <CODE>SpecialAddress.RECIPIENTS</CODE>, <CODE>SpecialAddress.TO</CODE>, 
1733:             * <CODE>SpecialAddress.NULL</CODE> and <CODE>SpecialAddress.UNALTERED</CODE>.<BR>
1734:             * <CODE>SpecialAddress.RECIPIENTS</CODE> is made equivalent to <CODE>SpecialAddress.TO</CODE>.<BR>
1735:             * <CODE>SpecialAddress.FROM</CODE> uses the From header if available, otherwise the Sender header if available,
1736:             * otherwise the return-path.<BR>
1737:             * <CODE>SpecialAddress.REPLY_TO</CODE> uses the ReplyTo header if available, otherwise the
1738:             * From header if available, otherwise the Sender header if available, otherwise the return-path.<BR>
1739:             * <CODE>SpecialAddress.UNALTERED</CODE> is ignored.<BR>
1740:             * Any other address is not replaced.<BR>
1741:             */
1742:            protected Collection replaceInternetAddresses(Mail mail,
1743:                    Collection list) throws MessagingException {
1744:                Collection newList = new HashSet(list.size());
1745:                Iterator iterator = list.iterator();
1746:                while (iterator.hasNext()) {
1747:                    InternetAddress internetAddress = (InternetAddress) iterator
1748:                            .next();
1749:                    MailAddress mailAddress = new MailAddress(internetAddress);
1750:                    if (!mailAddress.getHost().equalsIgnoreCase(
1751:                            "address.marker")) {
1752:                        newList.add(internetAddress);
1753:                    } else if (internetAddress.equals(SpecialAddress.SENDER
1754:                            .toInternetAddress())) {
1755:                        MailAddress sender = mail.getSender();
1756:                        if (sender != null) {
1757:                            newList.add(sender.toInternetAddress());
1758:                        }
1759:                    } else if (internetAddress
1760:                            .equals(SpecialAddress.REVERSE_PATH
1761:                                    .toInternetAddress())) {
1762:                        MailAddress reversePath = mail.getSender();
1763:                        if (reversePath != null) {
1764:                            newList.add(reversePath.toInternetAddress());
1765:                        }
1766:                    } else if (internetAddress.equals(SpecialAddress.FROM
1767:                            .toInternetAddress())) {
1768:                        try {
1769:                            InternetAddress[] fromArray = (InternetAddress[]) mail
1770:                                    .getMessage().getFrom();
1771:                            if (fromArray != null) {
1772:                                for (int i = 0; i < fromArray.length; i++) {
1773:                                    newList.add(fromArray[i]);
1774:                                }
1775:                            } else {
1776:                                MailAddress reversePath = mail.getSender();
1777:                                if (reversePath != null) {
1778:                                    newList
1779:                                            .add(reversePath
1780:                                                    .toInternetAddress());
1781:                                }
1782:                            }
1783:                        } catch (MessagingException me) {
1784:                            log("Unable to parse the \"FROM\" header in the original message; ignoring.");
1785:                        }
1786:                    } else if (internetAddress.equals(SpecialAddress.REPLY_TO
1787:                            .toInternetAddress())) {
1788:                        try {
1789:                            InternetAddress[] replyToArray = (InternetAddress[]) mail
1790:                                    .getMessage().getReplyTo();
1791:                            if (replyToArray != null) {
1792:                                for (int i = 0; i < replyToArray.length; i++) {
1793:                                    newList.add(replyToArray[i]);
1794:                                }
1795:                            } else {
1796:                                MailAddress reversePath = mail.getSender();
1797:                                if (reversePath != null) {
1798:                                    newList
1799:                                            .add(reversePath
1800:                                                    .toInternetAddress());
1801:                                }
1802:                            }
1803:                        } catch (MessagingException me) {
1804:                            log("Unable to parse the \"REPLY_TO\" header in the original message; ignoring.");
1805:                        }
1806:                    } else if (internetAddress.equals(SpecialAddress.TO
1807:                            .toInternetAddress())
1808:                            || internetAddress.equals(SpecialAddress.RECIPIENTS
1809:                                    .toInternetAddress())) {
1810:                        try {
1811:                            String[] toHeaders = mail.getMessage().getHeader(
1812:                                    RFC2822Headers.TO);
1813:                            if (toHeaders != null) {
1814:                                for (int i = 0; i < toHeaders.length; i++) {
1815:                                    try {
1816:                                        InternetAddress[] originalToInternetAddresses = InternetAddress
1817:                                                .parse(toHeaders[i], false);
1818:                                        for (int j = 0; j < originalToInternetAddresses.length; j++) {
1819:                                            newList
1820:                                                    .add(originalToInternetAddresses[j]);
1821:                                        }
1822:                                    } catch (MessagingException ae) {
1823:                                        log("Unable to parse a \"TO\" header address in the original message: "
1824:                                                + toHeaders[i] + "; ignoring.");
1825:                                    }
1826:                                }
1827:                            }
1828:                        } catch (MessagingException ae) {
1829:                            log("Unable to parse the \"TO\" header  in the original message; ignoring.");
1830:                        }
1831:                    } else if (internetAddress.equals(SpecialAddress.UNALTERED
1832:                            .toInternetAddress())) {
1833:                        continue;
1834:                    } else if (internetAddress.equals(SpecialAddress.NULL
1835:                            .toInternetAddress())) {
1836:                        continue;
1837:                    } else {
1838:                        newList.add(internetAddress);
1839:                    }
1840:                }
1841:                return newList;
1842:            }
1843:
1844:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.