1 /****************************************************************
2 * Licensed to the Apache Software Foundation (ASF) under one *
3 * or more contributor license agreements. See the NOTICE file *
4 * distributed with this work for additional information *
5 * regarding copyright ownership. The ASF licenses this file *
6 * to you under the Apache License, Version 2.0 (the *
7 * "License"); you may not use this file except in compliance *
8 * with the License. You may obtain a copy of the License at *
9 * *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, *
13 * software distributed under the License is distributed on an *
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
15 * KIND, either express or implied. See the License for the *
16 * specific language governing permissions and limitations *
17 * under the License. *
18 ****************************************************************/
19
20
21
22 package org.apache.james.transport.mailets;
23
24 import org.apache.mailet.base.GenericMailet;
25 import org.apache.mailet.Mail;
26 import org.apache.mailet.MailAddress;
27
28 import javax.mail.MessagingException;
29 import javax.mail.internet.InternetAddress;
30 import javax.mail.internet.MimeMessage;
31 import java.util.Collection;
32 import java.util.StringTokenizer;
33 import java.util.Vector;
34
35 /**
36 * <p>Mailet designed to process the recipients from the mail headers rather
37 * than the recipients specified in the SMTP message header. This can be
38 * useful if your mail is redirected on-route by a mail server that
39 * substitutes a fixed recipient address for the original.</p>
40 *
41 * <p>To use this, match against the redirection address using the
42 * <code>RecipientIs</code> matcher and set the mailet 'class' to
43 * <code>UseHeaderRecipients</code>. This will cause the email to be
44 * re-injected into the root process with the recipient substituted
45 * by all the recipients in the Mail-For, To and Cc headers
46 * of the message.</p>
47 *
48 * <p>e.g.</p>
49 * <pre><code>
50 * <mailet match="RecipientIs=forwarded@myhost"
51 * class="UseHeaderRecipients">
52 * </mailet>
53 * </code></pre>
54 *
55 * @version 1.0.0, 24/11/2000
56 */
57 public class UseHeaderRecipients extends GenericMailet {
58
59 /**
60 * Controls certain log messages
61 */
62 private boolean isDebug = false;
63
64 /**
65 * Initialize the mailet
66 *
67 * initializes the DEBUG flag
68 */
69 public void init() {
70 isDebug = (getInitParameter("debug") == null) ? false : new Boolean(getInitParameter("debug")).booleanValue();
71 }
72
73 /**
74 * Process an incoming email, removing the currently identified
75 * recipients and replacing them with the recipients indicated in
76 * the Mail-For, To and Cc headers of the actual email.
77 *
78 * @param mail incoming email
79 */
80 public void service(Mail mail) throws MessagingException {
81 MimeMessage message = mail.getMessage();
82
83 // Utilise features of Set Collections such that they automatically
84 // ensure that no two entries are equal using the equality method
85 // of the element objects. MailAddress objects test equality based
86 // on equivalent but not necessarily visually identical addresses.
87 Collection recipients = mail.getRecipients();
88 // Wipe all the exist recipients
89 recipients.clear();
90 recipients.addAll(getHeaderMailAddresses(message, "Mail-For"));
91 if (recipients.isEmpty()) {
92 recipients.addAll(getHeaderMailAddresses(message, "To"));
93 recipients.addAll(getHeaderMailAddresses(message, "Cc"));
94 }
95 if (isDebug) {
96 log("All recipients = " + recipients.toString());
97 log("Reprocessing mail using recipients in message headers");
98 }
99
100 // Return email to the "root" process.
101 getMailetContext().sendMail(mail.getSender(), mail.getRecipients(), mail.getMessage());
102 mail.setState(Mail.GHOST);
103 }
104
105
106 /**
107 * Return a string describing this mailet.
108 *
109 * @return a string describing this mailet
110 */
111 public String getMailetInfo() {
112 return "UseHeaderRecipients Mailet";
113 }
114
115 /**
116 * Work through all the headers of the email with a matching name and
117 * extract all the mail addresses as a collection of addresses.
118 *
119 * @param message the mail message to read
120 * @param name the header name as a String
121 * @return the collection of MailAddress objects.
122 */
123 private Collection getHeaderMailAddresses(MimeMessage message, String name) throws MessagingException {
124
125 if (isDebug) {
126 StringBuffer logBuffer =
127 new StringBuffer(64)
128 .append("Checking ")
129 .append(name)
130 .append(" headers");
131 log(logBuffer.toString());
132 }
133 Collection addresses = new Vector();
134 String[] headers = message.getHeader(name);
135 String addressString;
136 InternetAddress iAddress;
137 if (headers != null) {
138 for(int i = 0; i < headers.length; i++) {
139 StringTokenizer st = new StringTokenizer(headers[i], ",", false);
140 while (st.hasMoreTokens()) {
141 addressString = st.nextToken();
142 iAddress = new InternetAddress(addressString);
143 if (isDebug) {
144 log("Address = " + iAddress.toString());
145 }
146 addresses.add(new MailAddress(iAddress));
147 }
148 }
149 }
150 return addresses;
151 }
152
153 }