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 }