001: /****************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one *
003: * or more contributor license agreements. See the NOTICE file *
004: * distributed with this work for additional information *
005: * regarding copyright ownership. The ASF licenses this file *
006: * to you under the Apache License, Version 2.0 (the *
007: * "License"); you may not use this file except in compliance *
008: * with the License. You may obtain a copy of the License at *
009: * *
010: * http://www.apache.org/licenses/LICENSE-2.0 *
011: * *
012: * Unless required by applicable law or agreed to in writing, *
013: * software distributed under the License is distributed on an *
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015: * KIND, either express or implied. See the License for the *
016: * specific language governing permissions and limitations *
017: * under the License. *
018: ****************************************************************/package org.apache.james.transport.mailets;
019:
020: import org.apache.mailet.RFC2822Headers;
021: import org.apache.mailet.GenericMailet;
022: import org.apache.mailet.Mail;
023: import org.apache.mailet.MailAddress;
024: import org.apache.mailet.MailetException;
025:
026: import javax.mail.Address;
027: import javax.mail.Message;
028: import javax.mail.MessagingException;
029: import javax.mail.Session;
030: import javax.mail.internet.InternetAddress;
031: import javax.mail.internet.MimeBodyPart;
032: import javax.mail.internet.MimeMessage;
033: import javax.mail.internet.MimeMultipart;
034: import java.io.IOException;
035: import java.io.PrintWriter;
036: import java.io.StringWriter;
037: import java.util.Date;
038: import java.util.HashSet;
039: import java.util.Set;
040: import java.util.Collection;
041: import java.util.Iterator;
042: import java.util.ArrayList;
043:
044: /**
045: * <P>Generates a response to the reverse-path address.
046: * Note that this is different than a mail-client's
047: * reply, which would use the Reply-To or From header.</P>
048: * <P>Bounced messages are attached in their entirety (headers and
049: * content) and the resulting MIME part type is "message/rfc822".<BR>
050: * The reverse-path and the Return-Path header of the response is set to "null" ("<>"),
051: * meaning that no reply should be sent.</P>
052: * <P>A sender of the notification message can optionally be specified.
053: * If one is not specified, the postmaster's address will be used.<BR>
054: * A notice text can be specified, and in such case will be inserted into the
055: * notification inline text.<BR>
056: * If the notified message has an "error message" set, it will be inserted into the
057: * notification inline text. If the <CODE>attachStackTrace</CODE> init parameter
058: * is set to true, such error message will be attached to the notification message.<BR>
059: * <P>Supports the <CODE>passThrough</CODE> init parameter (true if missing).</P>
060: *
061: * <P>Sample configuration:</P>
062: * <PRE><CODE>
063: * <mailet match="All" class="Bounce">
064: * <sender><I>an address or postmaster or sender or unaltered, default=postmaster</I></sender>
065: * <attachError><I>true or false, default=false</I></attachError>
066: * <message><I>notice attached to the original message text (optional)</I></message>
067: * <prefix><I>optional subject prefix prepended to the original message</I></prefix>
068: * <inline><I>see {@link Resend}, default=none</I></inline>
069: * <attachment><I>see {@link Resend}, default=message</I></attachment>
070: * <passThrough><I>true or false, default=true</I></passThrough>
071: * <fakeDomainCheck><I>true or false, default=true</I></fakeDomainCheck>
072: * <debug><I>true or false, default=false</I></debug>
073: * </mailet>
074: * </CODE></PRE>
075: *
076: * <P>The behaviour of this mailet is equivalent to using Resend with the following
077: * configuration:</P>
078: * <PRE><CODE>
079: * <mailet match="All" class="Resend">
080: * <sender><I>an address or postmaster or sender or unaltered</I></sender>
081: * <attachError><I>true or false</I></attachError>
082: * <message><I><B>dynamically built</B></I></message>
083: * <prefix><I>a string</I></prefix>
084: * <passThrough>true or false</passThrough>
085: * <fakeDomainCheck><I>true or false</I></fakeDomainCheck>
086: * <recipients><B>sender</B></recipients>
087: * <reversePath>null</reversePath>
088: * <inline>see {@link Resend}</inline>
089: * <attachment>see {@link Resend}</attachment>
090: * <isReply>true</isReply>
091: * <debug><I>true or false</I></debug>
092: * </mailet>
093: * </CODE></PRE>
094: * <P><I>notice</I> and <I>sendingAddress</I> can be used instead of
095: * <I>message</I> and <I>sender</I>; such names are kept for backward compatibility.</P>
096: *
097: * @version CVS $Revision: 494012 $ $Date: 2007-01-08 11:23:58 +0100 (Mo, 08 Jan 2007) $
098: * @since 2.2.0
099: */
100: public class Bounce extends AbstractNotify {
101:
102: /**
103: * Return a string describing this mailet.
104: *
105: * @return a string describing this mailet
106: */
107: public String getMailetInfo() {
108: return "Bounce Mailet";
109: }
110:
111: /** Gets the expected init parameters. */
112: protected String[] getAllowedInitParameters() {
113: String[] allowedArray = {
114: // "static",
115: "debug", "passThrough", "fakeDomainCheck", "inline",
116: "attachment", "message", "notice", "sender",
117: "sendingAddress", "prefix", "attachError", };
118: return allowedArray;
119: }
120:
121: /* ******************************************************************** */
122: /* ****************** Begin of getX and setX methods ****************** */
123: /* ******************************************************************** */
124:
125: /**
126: * @return <CODE>SpecialAddress.REVERSE_PATH</CODE>
127: */
128: protected Collection getRecipients() {
129: Collection newRecipients = new HashSet();
130: newRecipients.add(SpecialAddress.REVERSE_PATH);
131: return newRecipients;
132: }
133:
134: /**
135: * @return <CODE>SpecialAddress.REVERSE_PATH</CODE>
136: */
137: protected InternetAddress[] getTo() {
138: InternetAddress[] apparentlyTo = new InternetAddress[1];
139: apparentlyTo[0] = SpecialAddress.REVERSE_PATH
140: .toInternetAddress();
141: return apparentlyTo;
142: }
143:
144: /**
145: * @return <CODE>SpecialAddress.NULL</CODE> (the meaning of bounce)
146: */
147: protected MailAddress getReversePath(Mail originalMail) {
148: return SpecialAddress.NULL;
149: }
150:
151: /* ******************************************************************** */
152: /* ******************* End of getX and setX methods ******************* */
153: /* ******************************************************************** */
154:
155: /**
156: * Service does the hard work,and redirects the originalMail in the form specified.
157: * Checks that the original return path is not empty,
158: * and then calls super.service(originalMail), otherwise just returns.
159: *
160: * @param originalMail the mail to process and redirect
161: * @throws MessagingException if a problem arises formulating the redirected mail
162: */
163: public void service(Mail originalMail) throws MessagingException {
164: if (originalMail.getSender() == null) {
165: if (isDebug)
166: log("Processing a bounce request for a message with an empty reverse-path. No bounce will be sent.");
167: if (!getPassThrough(originalMail)) {
168: originalMail.setState(Mail.GHOST);
169: }
170: return;
171: }
172:
173: if (isDebug)
174: log("Processing a bounce request for a message with a reverse path. The bounce will be sent to "
175: + originalMail.getSender().toString());
176:
177: super.service(originalMail);
178: }
179:
180: }
|