1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.james.transport.mailets;
23
24 import org.apache.james.Constants;
25 import org.apache.james.core.MailImpl;
26 import org.apache.james.impl.vut.VirtualUserTableUtil;
27 import org.apache.mailet.base.GenericMailet;
28 import org.apache.mailet.Mail;
29 import org.apache.mailet.MailAddress;
30 import org.apache.oro.text.regex.MalformedPatternException;
31
32 import javax.mail.MessagingException;
33 import javax.mail.internet.ParseException;
34
35 import java.util.ArrayList;
36 import java.util.Collection;
37 import java.util.HashMap;
38 import java.util.HashSet;
39 import java.util.Iterator;
40 import java.util.Map;
41 import java.util.StringTokenizer;
42
43
44
45
46
47
48 public abstract class AbstractVirtualUserTable extends GenericMailet
49 {
50 static private final String MARKER = "org.apache.james.transport.mailets.AbstractVirtualUserTable.mapped";
51
52
53
54
55
56
57
58
59 public void service(Mail mail) throws MessagingException
60 {
61 if (mail.getAttribute(MARKER) != null) {
62 mail.removeAttribute(MARKER);
63 return;
64 }
65
66 Collection recipientsToRemove = new HashSet();
67 Collection recipientsToAddLocal = new ArrayList();
68 Collection recipientsToAddForward = new ArrayList();
69
70 Collection recipients = mail.getRecipients();
71 Map recipientsMap = new HashMap(recipients.size());
72
73 for (Iterator iter = recipients.iterator(); iter.hasNext(); ) {
74 MailAddress address = (MailAddress)iter.next();
75
76
77 recipientsMap.put(address, null);
78 }
79
80 mapRecipients(recipientsMap);
81
82 for (Iterator iter = recipientsMap.keySet().iterator(); iter.hasNext(); ) {
83 MailAddress source = (MailAddress)iter.next();
84 String targetString = (String)recipientsMap.get(source);
85
86
87 if(targetString != null) {
88 if (targetString.startsWith("error:")) {
89
90 recipientsToRemove.add(source);
91 processDSN(mail, source, targetString);
92 } else {
93 StringTokenizer tokenizer = new StringTokenizer(targetString, getSeparator(targetString));
94
95 while (tokenizer.hasMoreTokens()) {
96 String targetAddress = tokenizer.nextToken().trim();
97
98
99
100 if (targetAddress.startsWith("regex:")) {
101 try {
102 targetAddress = VirtualUserTableUtil.regexMap(source, targetAddress);
103 } catch (MalformedPatternException e) {
104 log("Exception during regexMap processing: ", e);
105 }
106 if (targetAddress == null) continue;
107 }
108
109 try {
110 MailAddress target = (targetAddress.indexOf('@') < 0) ? new MailAddress(targetAddress, (String) getMailetContext().getAttribute(Constants.DEFAULT_DOMAIN))
111 : new MailAddress(targetAddress);
112
113
114 recipientsToRemove.add(source);
115
116
117
118 if (getMailetContext().isLocalServer(target.getHost())) {
119 recipientsToAddLocal.add(target);
120 } else {
121 recipientsToAddForward.add(target);
122 }
123
124 StringBuffer buf = new StringBuffer().append("Translating virtual user ")
125 .append(source)
126 .append(" to ")
127 .append(target);
128 log(buf.toString());
129
130 } catch (ParseException pe) {
131
132 StringBuffer exceptionBuffer =
133 new StringBuffer(128)
134 .append("There is an invalid map from ")
135 .append(source)
136 .append(" to ")
137 .append(targetAddress);
138 log(exceptionBuffer.toString());
139 continue;
140 }
141 }
142 }
143 }
144 }
145
146
147 recipients.removeAll(recipientsToRemove);
148
149
150 recipients.addAll(recipientsToAddLocal);
151
152
153
154
155
156
157
158
159
160
161 if (recipientsToAddForward.size() != 0) {
162
163
164
165
166 MailImpl newMail = new MailImpl(mail);
167 try {
168 newMail.setRemoteAddr(getMailetContext().getAttribute(Constants.HOSTADDRESS).toString());
169 newMail.setRemoteHost(getMailetContext().getAttribute(Constants.HOSTNAME).toString());
170
171 newMail.setRecipients(recipientsToAddForward);
172 newMail.setAttribute(MARKER, Boolean.TRUE);
173 getMailetContext().sendMail(newMail);
174 } finally {
175 newMail.dispose();
176 }
177 }
178
179
180 if (recipients.size() == 0) {
181 mail.setState(Mail.GHOST);
182 }
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198 protected abstract void mapRecipients(Map recipientsMap) throws MessagingException;
199
200
201
202
203
204
205
206
207 private void processDSN(Mail mail, MailAddress address, String error) {
208
209 int msgPos = error.indexOf(' ');
210 try {
211 Integer code = Integer.valueOf(error.substring("error:".length(),msgPos));
212 } catch (NumberFormatException e) {
213 log("Cannot send DSN. Exception parsing DSN code from: " + error, e);
214 return;
215 }
216 String msg = error.substring(msgPos + 1);
217
218 try {
219 getMailetContext().bounce(mail, error);
220 }
221 catch (MessagingException me) {
222 log("Cannot send DSN. Exception during DSN processing: ", me);
223 }
224 }
225
226
227
228
229
230
231
232 private String getSeparator(String targetString) {
233 return (targetString.indexOf(',') > -1 ? "," : (targetString.indexOf(';') > -1 ? ";" : (targetString.indexOf("regex:") > -1? "" : ":" )));
234 }
235
236 }