View Javadoc

1   /************************************************************************
2    * Copyright (c) 2000-2006 The Apache Software Foundation.             *
3    * All rights reserved.                                                *
4    * ------------------------------------------------------------------- *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you *
6    * may not use this file except in compliance with the License. You    *
7    * may obtain a copy of the License at:                                *
8    *                                                                     *
9    *     http://www.apache.org/licenses/LICENSE-2.0                      *
10   *                                                                     *
11   * Unless required by applicable law or agreed to in writing, software *
12   * distributed under the License is distributed on an "AS IS" BASIS,   *
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
14   * implied.  See the License for the specific language governing       *
15   * permissions and limitations under the License.                      *
16   ***********************************************************************/
17  
18  package org.apache.james.transport.mailets;
19  
20  import org.apache.mailet.RFC2822Headers;
21  import org.apache.mailet.GenericMailet;
22  import org.apache.mailet.Mail;
23  import org.apache.mailet.MailAddress;
24  import org.apache.mailet.MailetException;
25  
26  import javax.mail.Address;
27  import javax.mail.Message;
28  import javax.mail.MessagingException;
29  import javax.mail.Session;
30  import javax.mail.internet.InternetAddress;
31  import javax.mail.internet.MimeBodyPart;
32  import javax.mail.internet.MimeMessage;
33  import javax.mail.internet.MimeMultipart;
34  import java.io.IOException;
35  import java.io.PrintWriter;
36  import java.io.StringWriter;
37  import java.util.Date;
38  import java.util.HashSet;
39  import java.util.Set;
40  import java.util.Collection;
41  import java.util.Iterator;
42  import java.util.ArrayList;
43  
44  /***
45   * <P>Generates a response to the reverse-path address.
46   * Note that this is different than a mail-client's
47   * reply, which would use the Reply-To or From header.</P>
48   * <P>Bounced messages are attached in their entirety (headers and
49   * content) and the resulting MIME part type is "message/rfc822".<BR>
50   * The reverse-path and the Return-Path header of the response is set to "null" ("<>"),
51   * meaning that no reply should be sent.</P>
52   * <P>A sender of the notification message can optionally be specified.
53   * If one is not specified, the postmaster's address will be used.<BR>
54   * A notice text can be specified, and in such case will be inserted into the
55   * notification inline text.<BR>
56   * If the notified message has an "error message" set, it will be inserted into the
57   * notification inline text. If the <CODE>attachStackTrace</CODE> init parameter
58   * is set to true, such error message will be attached to the notification message.<BR>
59   * <P>Supports the <CODE>passThrough</CODE> init parameter (true if missing).</P>
60   *
61   * <P>Sample configuration:</P>
62   * <PRE><CODE>
63   * &lt;mailet match="All" class="Bounce">
64   *   &lt;sender&gt;<I>an address or postmaster or sender or unaltered, default=postmaster</I>&lt;/sender&gt;
65   *   &lt;attachError&gt;<I>true or false, default=false</I>&lt;/attachError&gt;
66   *   &lt;message&gt;<I>notice attached to the original message text (optional)</I>&lt;/message&gt;
67   *   &lt;prefix&gt;<I>optional subject prefix prepended to the original message</I>&lt;/prefix&gt;
68   *   &lt;inline&gt;<I>see {@link Resend}, default=none</I>&lt;/inline&gt;
69   *   &lt;attachment&gt;<I>see {@link Resend}, default=message</I>&lt;/attachment&gt;
70   *   &lt;passThrough&gt;<I>true or false, default=true</I>&lt;/passThrough&gt;
71   *   &lt;fakeDomainCheck&gt;<I>true or false, default=true</I>&lt;/fakeDomainCheck&gt;
72   *   &lt;debug&gt;<I>true or false, default=false</I>&lt;/debug&gt;
73   * &lt;/mailet&gt;
74   * </CODE></PRE>
75   *
76   * <P>The behaviour of this mailet is equivalent to using Resend with the following
77   * configuration:</P>
78   * <PRE><CODE>
79   * &lt;mailet match="All" class="Resend">
80   *   &lt;sender&gt;<I>an address or postmaster or sender or unaltered</I>&lt;/sender&gt;
81   *   &lt;attachError&gt;<I>true or false</I>&lt;/attachError&gt;
82   *   &lt;message&gt;<I><B>dynamically built</B></I>&lt;/message&gt;
83   *   &lt;prefix&gt;<I>a string</I>&lt;/prefix&gt;
84   *   &lt;passThrough&gt;true or false&lt;/passThrough&gt;
85   *   &lt;fakeDomainCheck&gt;<I>true or false</I>&lt;/fakeDomainCheck&gt;
86   *   &lt;recipients&gt;<B>sender</B>&lt;/recipients&gt;
87   *   &lt;reversePath&gt;null&lt;/reversePath&gt;
88   *   &lt;inline&gt;see {@link Resend}&lt;/inline&gt;
89   *   &lt;attachment&gt;see {@link Resend}&lt;/attachment&gt;
90   *   &lt;isReply&gt;true&lt;/isReply&gt;
91   *   &lt;debug&gt;<I>true or false</I>&lt;/debug&gt;
92   * &lt;/mailet&gt;
93   * </CODE></PRE>
94   * <P><I>notice</I> and <I>sendingAddress</I> can be used instead of
95   * <I>message</I> and <I>sender</I>; such names are kept for backward compatibility.</P>
96   *
97   * @version CVS $Revision: 365582 $ $Date: 2006-01-03 08:51:21 +0000 (mar, 03 gen 2006) $
98   * @since 2.2.0
99   */
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",
116             "passThrough",
117             "fakeDomainCheck",
118             "inline",
119             "attachment",
120             "message",
121             "notice",
122             "sender",
123             "sendingAddress",
124             "prefix",
125             "attachError",
126         };
127         return allowedArray;
128     }
129     
130     /* ******************************************************************** */
131     /* ****************** Begin of getX and setX methods ****************** */
132     /* ******************************************************************** */
133 
134     /***
135      * @return <CODE>SpecialAddress.REVERSE_PATH</CODE>
136      */
137     protected Collection getRecipients() {
138         Collection newRecipients = new HashSet();
139         newRecipients.add(SpecialAddress.REVERSE_PATH);
140         return newRecipients;
141     }
142 
143     /***
144      * @return <CODE>SpecialAddress.REVERSE_PATH</CODE>
145      */
146     protected InternetAddress[] getTo() {
147         InternetAddress[] apparentlyTo = new InternetAddress[1];
148         apparentlyTo[0] = SpecialAddress.REVERSE_PATH.toInternetAddress();
149         return apparentlyTo;
150     }
151 
152     /***
153      * @return <CODE>SpecialAddress.NULL</CODE> (the meaning of bounce)
154      */
155     protected MailAddress getReversePath(Mail originalMail) {
156         return SpecialAddress.NULL;
157     }
158 
159     /* ******************************************************************** */
160     /* ******************* End of getX and setX methods ******************* */
161     /* ******************************************************************** */
162 
163     /***
164      * Service does the hard work,and redirects the originalMail in the form specified.
165      * Checks that the original return path is not empty,
166      * and then calls super.service(originalMail), otherwise just returns.
167      *
168      * @param originalMail the mail to process and redirect
169      * @throws MessagingException if a problem arises formulating the redirected mail
170      */
171     public void service(Mail originalMail) throws MessagingException {
172         if (originalMail.getSender() == null) {
173             if (isDebug)
174                 log("Processing a bounce request for a message with an empty reverse-path.  No bounce will be sent.");
175             if(!getPassThrough(originalMail)) {
176                 originalMail.setState(Mail.GHOST);
177             }
178             return;
179         }
180 
181         if (isDebug)
182             log("Processing a bounce request for a message with a reverse path.  The bounce will be sent to " + originalMail.getSender().toString());
183 
184         super.service(originalMail);
185     }
186 
187 }
188