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.Mail;
022: import org.apache.mailet.MailAddress;
023:
024: import javax.mail.MessagingException;
025: import javax.mail.internet.InternetAddress;
026: import javax.mail.internet.MimeMessage;
027: import java.io.PrintWriter;
028: import java.io.StringWriter;
029: import java.util.Collection;
030: import java.util.Iterator;
031:
032: /**
033: * <P>Abstract mailet providing configurable notification services.<BR>
034: * This mailet can be subclassed to make authoring notification mailets simple.<BR>
035: * <P>Provides the following functionalities to all notification subclasses:</P>
036: * <UL>
037: * <LI>A common notification message layout.</LI>
038: * <LI>A sender of the notification message can optionally be specified.
039: * If one is not specified, the postmaster's address will be used.</LI>
040: * <LI>A notice text can be specified, and in such case will be inserted into the
041: * notification inline text.</LI>
042: * <LI>If the notified message has an "error message" set, it will be inserted into the
043: * notification inline text. If the <CODE>attachStackTrace</CODE> init parameter
044: * is set to true, such error message will be attached to the notification message.</LI>
045: * <LI>The notified messages are attached in their entirety (headers and
046: * content) and the resulting MIME part type is "message/rfc822".</LI>
047: * <LI>Supports by default the <CODE>passThrough</CODE> init parameter (true if missing).</LI>
048: * </UL>
049: *
050: * <P>Sample configuration common to all notification mailet subclasses:</P>
051: * <PRE><CODE>
052: * <mailet match="All" class="<I>a notification mailet</I>">
053: * <sender><I>an address or postmaster or sender or unaltered, default=postmaster</I></sender>
054: * <attachError><I>true or false, default=false</I></attachError>
055: * <message><I>notice attached to the original message text (optional)</I></message>
056: * <prefix><I>optional subject prefix prepended to the original message</I></prefix>
057: * <inline><I>see {@link Redirect}, default=none</I></inline>
058: * <attachment><I>see {@link Redirect}, default=message</I></attachment>
059: * <passThrough><I>true or false, default=true</I></passThrough>
060: * <fakeDomainCheck><I>true or false, default=true</I></fakeDomainCheck>
061: * <debug><I>true or false, default=false</I></debug>
062: * </mailet>
063: * </CODE></PRE>
064: * <P><I>notice</I> and <I>senderAddress</I> can be used instead of
065: * <I>message</I> and <I>sender</I>; such names are kept for backward compatibility.</P>
066: *
067: * @version CVS $Revision: 494012 $ $Date: 2007-01-08 11:23:58 +0100 (Mo, 08 Jan 2007) $
068: * @since 2.2.0
069: */
070: public abstract class AbstractNotify extends AbstractRedirect {
071:
072: /* ******************************************************************** */
073: /* ****************** Begin of getX and setX methods ****************** */
074: /* ******************************************************************** */
075:
076: /**
077: * @return the <CODE>passThrough</CODE> init parameter, or true if missing
078: */
079: protected boolean getPassThrough() throws MessagingException {
080: return new Boolean(getInitParameter("passThrough", "true"))
081: .booleanValue();
082: }
083:
084: /**
085: * @return the <CODE>inline</CODE> init parameter, or <CODE>NONE</CODE> if missing
086: */
087: protected int getInLineType() throws MessagingException {
088: return getTypeCode(getInitParameter("inline", "none"));
089: }
090:
091: /**
092: * @return the <CODE>attachment</CODE> init parameter, or <CODE>MESSAGE</CODE> if missing
093: */
094: protected int getAttachmentType() throws MessagingException {
095: return getTypeCode(getInitParameter("attachment", "message"));
096: }
097:
098: /**
099: * @return the <CODE>notice</CODE> init parameter,
100: * or the <CODE>message</CODE> init parameter if missing,
101: * or a default string if both are missing
102: */
103: protected String getMessage() {
104: return getInitParameter(
105: "notice",
106: getInitParameter(
107: "message",
108: "We were unable to deliver the attached message because of an error in the mail server."));
109: }
110:
111: /**
112: * @return the full message to append, built from the Mail object
113: */
114: protected String getMessage(Mail originalMail)
115: throws MessagingException {
116: MimeMessage message = originalMail.getMessage();
117: StringWriter sout = new StringWriter();
118: PrintWriter out = new PrintWriter(sout, true);
119:
120: // First add the "local" notice
121: // (either from conf or generic error message)
122: out.println(getMessage());
123: // And then the message from other mailets
124: if (originalMail.getErrorMessage() != null) {
125: out.println();
126: out.println("Error message below:");
127: out.println(originalMail.getErrorMessage());
128: }
129: out.println();
130: out.println("Message details:");
131:
132: if (message.getSubject() != null) {
133: out.println(" Subject: " + message.getSubject());
134: }
135: if (message.getSentDate() != null) {
136: out.println(" Sent date: " + message.getSentDate());
137: }
138: out.println(" MAIL FROM: " + originalMail.getSender());
139: Iterator rcptTo = originalMail.getRecipients().iterator();
140: out.println(" RCPT TO: " + rcptTo.next());
141: while (rcptTo.hasNext()) {
142: out.println(" " + rcptTo.next());
143: }
144: String[] addresses = null;
145: addresses = message.getHeader(RFC2822Headers.FROM);
146: if (addresses != null) {
147: out.print(" From: ");
148: for (int i = 0; i < addresses.length; i++) {
149: out.print(addresses[i] + " ");
150: }
151: out.println();
152: }
153: addresses = message.getHeader(RFC2822Headers.TO);
154: if (addresses != null) {
155: out.print(" To: ");
156: for (int i = 0; i < addresses.length; i++) {
157: out.print(addresses[i] + " ");
158: }
159: out.println();
160: }
161: addresses = message.getHeader(RFC2822Headers.CC);
162: if (addresses != null) {
163: out.print(" CC: ");
164: for (int i = 0; i < addresses.length; i++) {
165: out.print(addresses[i] + " ");
166: }
167: out.println();
168: }
169: out.println(" Size (in bytes): " + message.getSize());
170: if (message.getLineCount() >= 0) {
171: out.println(" Number of lines: " + message.getLineCount());
172: }
173:
174: return sout.toString();
175: }
176:
177: // All subclasses of AbstractNotify are expected to establish their own recipients
178: abstract protected Collection getRecipients()
179: throws MessagingException;
180:
181: /**
182: * @return null
183: */
184: protected InternetAddress[] getTo() throws MessagingException {
185: return null;
186: }
187:
188: /**
189: * @return <CODE>SpecialAddress.NULL</CODE>, that will remove the "ReplyTo:" header
190: */
191: protected MailAddress getReplyTo() throws MessagingException {
192: return SpecialAddress.NULL;
193: }
194:
195: /**
196: * @return {@link AbstractRedirect#getSender(Mail)}, meaning the new requested sender if any
197: */
198: protected MailAddress getReversePath(Mail originalMail)
199: throws MessagingException {
200: return getSender(originalMail);
201: }
202:
203: /**
204: * @return the value of the <CODE>sendingAddress</CODE> init parameter,
205: * or the value of the <CODE>sender</CODE> init parameter if missing,
206: * or the postmaster address if both are missing
207: * @return the <CODE>sendingAddress</CODE> init parameter
208: * or the <CODE>sender</CODE> init parameter
209: * or the postmaster address if both are missing;
210: * possible special addresses returned are
211: * <CODE>SpecialAddress.SENDER</CODE>
212: * and <CODE>SpecialAddress.UNALTERED</CODE>
213: */
214: protected MailAddress getSender() throws MessagingException {
215: String addressString = getInitParameter("sendingAddress",
216: getInitParameter("sender"));
217:
218: if (addressString == null) {
219: return getMailetContext().getPostmaster();
220: }
221:
222: MailAddress specialAddress = getSpecialAddress(addressString,
223: new String[] { "postmaster", "sender", "unaltered" });
224: if (specialAddress != null) {
225: return specialAddress;
226: }
227:
228: try {
229: return new MailAddress(addressString);
230: } catch (Exception e) {
231: throw new MessagingException(
232: "Exception thrown in getSender() parsing: "
233: + addressString, e);
234: }
235: }
236:
237: /**
238: * @return null
239: */
240: protected String getSubject() throws MessagingException {
241: return null;
242: }
243:
244: /**
245: * @return the <CODE>prefix</CODE> init parameter or "Re:" if missing
246: */
247: protected String getSubjectPrefix() {
248: return getInitParameter("prefix", "Re:");
249: }
250:
251: /**
252: * Builds the subject of <I>newMail</I> appending the subject
253: * of <I>originalMail</I> to <I>subjectPrefix</I>, but avoiding a duplicate.
254: */
255: protected void setSubjectPrefix(Mail newMail, String subjectPrefix,
256: Mail originalMail) throws MessagingException {
257: String subject = originalMail.getMessage().getSubject();
258: if (subject == null) {
259: subject = "";
260: }
261: if (subjectPrefix == null
262: || subject.indexOf(subjectPrefix) == 0) {
263: newMail.getMessage().setSubject(subject);
264: } else {
265: newMail.getMessage().setSubject(subjectPrefix + subject);
266: }
267: }
268:
269: /**
270: * @return true
271: */
272: protected boolean isReply() {
273: return true;
274: }
275:
276: /* ******************************************************************** */
277: /* ******************* End of getX and setX methods ******************* */
278: /* ******************************************************************** */
279:
280: }
|