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 * <mailet match="All" class="Bounce">
64 * <sender><I>an address or postmaster or sender or unaltered, default=postmaster</I></sender>
65 * <attachError><I>true or false, default=false</I></attachError>
66 * <message><I>notice attached to the original message text (optional)</I></message>
67 * <prefix><I>optional subject prefix prepended to the original message</I></prefix>
68 * <inline><I>see {@link Resend}, default=none</I></inline>
69 * <attachment><I>see {@link Resend}, default=message</I></attachment>
70 * <passThrough><I>true or false, default=true</I></passThrough>
71 * <fakeDomainCheck><I>true or false, default=true</I></fakeDomainCheck>
72 * <debug><I>true or false, default=false</I></debug>
73 * </mailet>
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 * <mailet match="All" class="Resend">
80 * <sender><I>an address or postmaster or sender or unaltered</I></sender>
81 * <attachError><I>true or false</I></attachError>
82 * <message><I><B>dynamically built</B></I></message>
83 * <prefix><I>a string</I></prefix>
84 * <passThrough>true or false</passThrough>
85 * <fakeDomainCheck><I>true or false</I></fakeDomainCheck>
86 * <recipients><B>sender</B></recipients>
87 * <reversePath>null</reversePath>
88 * <inline>see {@link Resend}</inline>
89 * <attachment>see {@link Resend}</attachment>
90 * <isReply>true</isReply>
91 * <debug><I>true or false</I></debug>
92 * </mailet>
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
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
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
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