View Javadoc

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.MailetUtil;
25  import org.apache.mailet.base.RFC2822Headers;
26  import org.apache.mailet.base.GenericMailet;
27  import org.apache.mailet.Mail;
28  import org.apache.mailet.MailAddress;
29  import org.apache.mailet.MailetException;
30  
31  import javax.mail.MessagingException;
32  import javax.mail.internet.MimeMessage;
33  import javax.mail.internet.MimeMultipart;
34  import java.io.IOException;
35  import java.util.Collection;
36  
37  /**
38   * An abstract implementation of a listserv.  The underlying implementation must define
39   * various settings, and can vary in their individual configuration.  Supports restricting
40   * to members only, allowing attachments or not, sending replies back to the list, and an
41   * optional subject prefix.
42   */
43  public abstract class GenericListserv extends GenericMailet {
44  
45      /**
46       * Returns a Collection of MailAddress objects of members to receive this email
47       */
48      public abstract Collection getMembers() throws MessagingException;
49  
50      /**
51       * Returns whether this list should restrict to senders only
52       */
53      public abstract boolean isMembersOnly() throws MessagingException;
54  
55      /**
56       * Returns whether this listserv allow attachments
57       */
58      public abstract boolean isAttachmentsAllowed() throws MessagingException;
59  
60      /**
61       * Returns whether listserv should add reply-to header
62       */
63      public abstract boolean isReplyToList() throws MessagingException;
64  
65      /**
66       * The email address that this listserv processes on.  If returns null, will use the
67       * recipient of the message, which hopefully will be the correct email address assuming
68       * the matcher was properly specified.
69       */
70      public MailAddress getListservAddress() throws MessagingException {
71          return null;
72      }
73  
74      /**
75       * An optional subject prefix.
76       */
77      public abstract String getSubjectPrefix() throws MessagingException;
78  
79      /**
80       * Should the subject prefix be automatically surrounded by [].
81       *
82       * @return whether the subject prefix will be surrounded by []
83       *
84       * @throws MessagingException never, for this implementation
85       */
86      public boolean isPrefixAutoBracketed() throws MessagingException {
87          return true; // preserve old behavior unless subclass overrides.
88      }
89  
90      
91      /**
92       * Processes the message.  Assumes it is the only recipient of this forked message.
93       */
94      public final void service(Mail mail) throws MessagingException {
95          try {
96              Collection members = getMembers();
97  
98              //Check for members only flag....
99              if (isMembersOnly() && !members.contains(mail.getSender())) {
100                 //Need to bounce the message to say they can't send to this list
101                 getMailetContext().bounce(mail, "Only members of this listserv are allowed to send a message to this address.");
102                 mail.setState(Mail.GHOST);
103                 return;
104             }
105 
106             //Check for no attachments
107             if (!isAttachmentsAllowed() && mail.getMessage().getContent() instanceof MimeMultipart) {
108                 getMailetContext().bounce(mail, "You cannot send attachments to this listserv.");
109                 mail.setState(Mail.GHOST);
110                 return;
111             }
112 
113             //Create a copy of this message to send out
114             MimeMessage message = new MimeMessage(mail.getMessage());
115             //We need to remove this header from the copy we're sending around
116             message.removeHeader(RFC2822Headers.RETURN_PATH);
117 
118             //Figure out the listserv address.
119             MailAddress listservAddr = getListservAddress();
120             if (listservAddr == null) {
121                 //Use the recipient
122                 listservAddr = (MailAddress)mail.getRecipients().iterator().next();
123             }
124 
125             //Check if the X-been-there header is set to the listserv's name
126             //  (the address).  If it has, this means it's a message from this
127             //  listserv that's getting bounced back, so we need to swallow it
128             if (listservAddr.equals(message.getHeader("X-been-there"))) {
129                 mail.setState(Mail.GHOST);
130                 return;
131             }
132 
133             //Set the subject if set
134             String prefix = getSubjectPrefix();
135             if (prefix != null) {
136                 if (isPrefixAutoBracketed()) {
137                     StringBuffer prefixBuffer =
138                         new StringBuffer(64)
139                             .append("[")
140                             .append(prefix)
141                             .append("] ");
142                     prefix = prefixBuffer.toString();
143                 }
144                 String subj = message.getSubject();
145                 if (subj == null) {
146                     subj = "";
147                 }
148                 subj = MailetUtil.normalizeSubject(subj, prefix);
149                 AbstractRedirect.changeSubject(message, subj);
150             }
151 
152             //If replies should go to this list, we need to set the header
153             if (isReplyToList()) {
154                 message.setHeader(RFC2822Headers.REPLY_TO, listservAddr.toString());
155             }
156             //We're going to set this special header to avoid bounces
157             //  getting sent back out to the list
158             message.setHeader("X-been-there", listservAddr.toString());
159 
160             //Send the message to the list members
161             //We set the postmaster as the sender for now so bounces go to him/her
162             getMailetContext().sendMail(getMailetContext().getPostmaster(), members, message);
163 
164             //Kill the old message
165             mail.setState(Mail.GHOST);
166         } catch (IOException ioe) {
167             throw new MailetException("Error creating listserv message", ioe);
168         }
169     }
170 }