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  package org.apache.jsieve.mailet;
20  
21  import javax.mail.MessagingException;
22  import javax.mail.internet.MimeMessage;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.jsieve.mail.Action;
26  import org.apache.jsieve.mail.ActionFileInto;
27  import org.apache.mailet.Mail;
28  import org.apache.mailet.MailAddress;
29  
30  public class FileIntoAction implements MailAction {
31      
32      private static final char HIERARCHY_DELIMITER = '.';
33  
34      public void execute(Action action, Mail mail, ActionContext context) throws MessagingException {
35          if (action instanceof ActionFileInto) {
36              final ActionFileInto fileIntoAction = (ActionFileInto) action;
37              execute(fileIntoAction, mail, context);
38          }
39      }
40  
41      /**
42       * <p>
43       * Executes the passed ActionFileInto.
44       * </p>
45       * 
46       * <p>
47       * This implementation accepts any destination with the root of <code>INBOX</code>.
48       * </p>
49       * 
50       * <p>
51       * As the current POP3 server does not support sub-folders, the mail is
52       * stored in the INBOX for the recipient of the mail and the full intended
53       * destination added as a prefix to the message's subject.
54       * </p>
55       * 
56       * <p>
57       * When IMAP support is added to James, it will be possible to support
58       * sub-folders of <code>INBOX</code> fully.
59       * </p>
60       * 
61       * @param anAction
62       * @param aMail
63       * @param context not null
64       * @throws MessagingException
65       */
66      public void execute(ActionFileInto anAction, Mail aMail, final ActionContext context) throws MessagingException
67      {
68          String destinationMailbox = anAction.getDestination();
69          MailAddress recipient;
70          boolean delivered = false;
71          try
72          {
73              recipient = ActionUtils.getSoleRecipient(aMail);
74              MimeMessage localMessage = createMimeMessage(aMail, recipient);
75              
76              if (!(destinationMailbox.length() > 0 
77                      && destinationMailbox.charAt(0) == HIERARCHY_DELIMITER)) {
78                  destinationMailbox =  HIERARCHY_DELIMITER + destinationMailbox;
79              }
80              
81              final String mailbox = destinationMailbox.replace(HIERARCHY_DELIMITER, '/');
82              final String host;
83              if (mailbox.charAt(0) == '/') {
84                  host = "@localhost";
85              } else {
86                  host = "@localhost/";
87              }
88              final String url = "mailbox://" + recipient.getUser() + host + mailbox;
89              //TODO: copying this message so many times seems a waste
90              context.post(url, localMessage);
91              delivered = true;
92          }
93          catch (MessagingException ex)
94          {
95              final Log log = context.getLog();
96              if (log.isDebugEnabled()) {
97                  log.debug("Error while storing mail into. "+destinationMailbox, ex);
98              }
99              throw ex;
100         }
101         finally
102         {
103             // Ensure the mail is always ghosted
104             aMail.setState(Mail.GHOST);
105         }
106         if (delivered)
107         {
108             final Log log = context.getLog();
109             if (log.isDebugEnabled()) {
110                 log.debug("Filed Message ID: "
111                     + aMail.getMessage().getMessageID()
112                     + " into destination: \""
113                     + destinationMailbox + "\"");
114             }
115         }
116     }
117     
118     private static MimeMessage createMimeMessage(Mail aMail, MailAddress recipient) throws MessagingException {
119         // Adapted from LocalDelivery Mailet
120         // Add qmail's de facto standard Delivered-To header
121         MimeMessage localMessage = new MimeMessage(aMail.getMessage())
122         {
123             protected void updateHeaders() throws MessagingException
124             {
125                 if (getMessageID() == null)
126                     super.updateHeaders();
127                 else
128                     modified = false;
129             }
130         };
131         localMessage.addHeader("Delivered-To", recipient.toString());
132 
133         localMessage.saveChanges();
134         return localMessage;
135     }
136 }