mitm.application.djigzo.james.mailets.PDFEncryptTest.java Source code

Java tutorial

Introduction

Here is the source code for mitm.application.djigzo.james.mailets.PDFEncryptTest.java

Source

/*
 * Copyright (c) 2008-2011, Martijn Brinkers, Djigzo.
 * 
 * This file is part of Djigzo email encryption.
 *
 * Djigzo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License 
 * version 3, 19 November 2007 as published by the Free Software 
 * Foundation.
 *
 * Djigzo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public 
 * License along with Djigzo. If not, see <http://www.gnu.org/licenses/>
 *
 * Additional permission under GNU AGPL version 3 section 7
 * 
 * If you modify this Program, or any covered work, by linking or 
 * combining it with aspectjrt.jar, aspectjweaver.jar, tyrex-1.0.3.jar, 
 * freemarker.jar, dom4j.jar, mx4j-jmx.jar, mx4j-tools.jar, 
 * spice-classman-1.0.jar, spice-loggerstore-0.5.jar, spice-salt-0.8.jar, 
 * spice-xmlpolicy-1.0.jar, saaj-api-1.3.jar, saaj-impl-1.3.jar, 
 * wsdl4j-1.6.1.jar (or modified versions of these libraries), 
 * containing parts covered by the terms of Eclipse Public License, 
 * tyrex license, freemarker license, dom4j license, mx4j license,
 * Spice Software License, Common Development and Distribution License
 * (CDDL), Common Public License (CPL) the licensors of this Program grant 
 * you additional permission to convey the resulting work.
 */
package mitm.application.djigzo.james.mailets;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;

import javax.mail.BodyPart;
import javax.mail.Multipart;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import mitm.application.djigzo.AutoTransactDelegator;
import mitm.application.djigzo.DjigzoTestUtils;
import mitm.application.djigzo.james.DjigzoMailAttributesImpl;
import mitm.application.djigzo.james.PasswordContainer;
import mitm.application.djigzo.james.Passwords;
import mitm.application.djigzo.james.mock.MockMail;
import mitm.application.djigzo.james.mock.MockMailetConfig;
import mitm.application.djigzo.james.mock.SendMailEventListenerImpl;
import mitm.common.locale.CharacterEncoding;
import mitm.common.mail.BodyPartUtils;
import mitm.common.mail.MailUtils;
import mitm.common.util.MiscStringUtils;
import mitm.test.TestUtils;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.james.smtpserver.SMTPSession;
import org.apache.log4j.LogManager;
import org.apache.mailet.Mail;
import org.apache.mailet.MailAddress;
import org.apache.mailet.Mailet;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.lowagie.text.pdf.PdfReader;

public class PDFEncryptTest {
    private final static File testBase = new File("test/resources/testdata");
    private static final File tempDir = new File("test/tmp");

    private AutoTransactDelegator autoTransactDelegator;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        DjigzoTestUtils.initialize();

        LogManager.getLogger(PDFEncrypt.class).setLevel(org.apache.log4j.Level.DEBUG);
    }

    @Before
    public void setup() throws Exception {
        DjigzoTestUtils.recreateTables();

        autoTransactDelegator = AutoTransactDelegator.createProxy();
    }

    private void checkEncryption(MimeMessage message, String password, boolean hasReplyLink) throws Exception {
        /*
         * The message should be a mime multipart mixed with two parts. The first part should be readable text
         * and the second part should be the encrypted PDF
         */
        assertTrue(message.isMimeType("multipart/mixed"));

        Multipart mp = (Multipart) message.getContent();

        assertEquals(2, mp.getCount());

        BodyPart textPart = mp.getBodyPart(0);

        assertTrue(textPart.isMimeType("text/plain"));

        BodyPart pdfPart = mp.getBodyPart(1);

        assertTrue(pdfPart.isMimeType("application/pdf"));

        PdfReader reader = new PdfReader(pdfPart.getInputStream(), password.getBytes(CharacterEncoding.US_ASCII));

        String firstPageContent = new String(reader.getPageContent(1), CharacterEncoding.US_ASCII);

        /*
         * We just check whether the raw content contains (Reply) or not.
         */
        if (hasReplyLink) {
            assertTrue(firstPageContent.contains("(Reply)"));

            assertTrue(((String) textPart.getContent()).contains("reply URL: http://127.0.0.1?env="));
        } else {
            assertFalse(firstPageContent.contains("(Reply)"));
        }
    }

    @Test
    public void testReplyInvalidFrom() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        Mailet mailet = new PDFEncrypt();

        String template = FileUtils.readFileToString(new File("test/resources/templates/pdf-attachment.ftl"));

        autoTransactDelegator.setGlobalProperty("pdfTemplate", template);
        autoTransactDelegator.setGlobalProperty("user.serverSecret", "123", true /* encrypt */);
        autoTransactDelegator.setGlobalProperty("user.pdf.replyAllowed", "true");
        autoTransactDelegator.setGlobalProperty("user.pdf.replyURL", "http://127.0.0.1");

        autoTransactDelegator.setProperty("m.brinkers@pobox.com", "user.pdf.replyAllowed", "true");

        mailetConfig.setInitParameter("log", "starting");
        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("templateProperty", "pdfTemplate");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        mail.setState(Mail.DEFAULT);

        Passwords passwords = new Passwords();

        PasswordContainer container = new PasswordContainer("test", "test ID");

        passwords.put("m.brinkers@pobox.com", container);

        new DjigzoMailAttributesImpl(mail).setPasswords(passwords);

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        message.setFrom(new InternetAddress("&*^&*^&*", false));

        message.saveChanges();

        mail.setMessage(message);

        Collection<MailAddress> recipients = new LinkedList<MailAddress>();

        recipients.add(new MailAddress("m.bRINKERs@pobox.com"));

        mail.setRecipients(recipients);

        mail.setSender(null);

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testUserTemplateEncryptPDF", listener.getMessages());

        assertEquals(1, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals(1, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.bRINKERs@pobox.com")));
        assertNull(listener.getSenders().get(0));
        assertEquals(Mail.DEFAULT, mail.getState());

        message = listener.getMessages().get(0);

        assertNotNull(message);

        MailUtils.validateMessage(message);

        checkEncryption(message, "test", false);
    }

    @Test
    public void testReply() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        Mailet mailet = new PDFEncrypt();

        String template = FileUtils.readFileToString(new File("test/resources/templates/pdf-attachment.ftl"));

        autoTransactDelegator.setProperty("test@EXAMPLE.com", "pdfTemplate", template);

        autoTransactDelegator.setProperty("test@example.com", "user.serverSecret", "123", true /* encrypt */);
        autoTransactDelegator.setProperty("test@example.com", "user.pdf.replyAllowed", "true");
        autoTransactDelegator.setProperty("test@example.com", "user.pdf.replyURL", "http://127.0.0.1");

        autoTransactDelegator.setProperty("m.brinkers@pobox.com", "user.pdf.replyAllowed", "true");

        mailetConfig.setInitParameter("log", "starting");
        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("templateProperty", "pdfTemplate");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");
        mailetConfig.setInitParameter("ownerPasswordMode", "random");
        mailetConfig.setInitParameter("openPermission", "allowPrinting");
        mailetConfig.setInitParameter("openPermission", "allowAssembly");
        mailetConfig.setInitParameter("viewerPreference", "centerWindow");
        mailetConfig.setInitParameter("viewerPreference", "fitWindow");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        mail.setState(Mail.DEFAULT);

        Passwords passwords = new Passwords();

        PasswordContainer container = new PasswordContainer("test1", "test ID");

        passwords.put("m.brinkers@pobox.com", container);

        container = new PasswordContainer("test2", "test ID 2");

        passwords.put("123@example.com", container);

        new DjigzoMailAttributesImpl(mail).setPasswords(passwords);

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        Collection<MailAddress> recipients = new LinkedList<MailAddress>();

        recipients.add(new MailAddress("m.bRINKERs@pobox.com"));
        recipients.add(new MailAddress("123@EXAMPLE.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testUserTemplateEncryptPDF", listener.getMessages());

        assertEquals(2, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals("encryptedProcessor", listener.getStates().get(1));
        assertEquals(1, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.bRINKERs@pobox.com")));
        assertEquals(1, listener.getRecipients().get(1).size());
        assertTrue(listener.getRecipients().get(1).contains(new MailAddress("123@EXAMPLE.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals("sender@example.com", listener.getSenders().get(1).toString());
        assertEquals(Mail.DEFAULT, mail.getState());

        MimeMessage message0 = listener.getMessages().get(0);
        MimeMessage message1 = listener.getMessages().get(1);

        assertNotNull(message0);
        assertNotNull(message1);

        assertEquals("test", StringUtils.join(message0.getHeader("X-pdf-template-test")));
        assertEquals("test", StringUtils.join(message1.getHeader("X-pdf-template-test")));

        MailUtils.validateMessage(message0);
        MailUtils.validateMessage(message1);

        checkEncryption(message0, "test1", true);
        checkEncryption(message1, "test2", false);
    }

    /*
     * Test the encryption of a message with a large body text (640K)
     */
    @Test
    public void testPerformanceLargeAttachment() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        Mailet mailet = new PDFEncrypt();

        String template = FileUtils.readFileToString(new File("test/resources/templates/pdf-attachment.ftl"));

        autoTransactDelegator.setProperty("martijn@djigzo.com", "pdfTemplate", template);

        mailetConfig.setInitParameter("log", "starting");
        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("templateProperty", "pdfTemplate");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");

        mailet.init(mailetConfig);

        int repeat = 100;

        long start = System.currentTimeMillis();

        for (int i = 0; i < repeat; i++) {
            MockMail mail = new MockMail();

            mail.setState(Mail.DEFAULT);

            Passwords passwords = new Passwords();

            PasswordContainer container = new PasswordContainer("test1", "test ID");

            passwords.put("m.brinkers@pobox.com", container);

            new DjigzoMailAttributesImpl(mail).setPasswords(passwords);

            MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/multiple-attachments.eml"));

            mail.setMessage(message);

            Collection<MailAddress> recipients = new LinkedList<MailAddress>();

            recipients.add(new MailAddress("m.bRINKERs@pobox.com"));

            mail.setRecipients(recipients);

            mail.setSender(new MailAddress("sender@example.com"));

            mailet.service(mail);

            MailUtils.validateMessage(listener.getMessages().get(0));
        }

        long diff = System.currentTimeMillis() - start;

        double perSecond = repeat * 1000.0 / diff;

        System.out.println("PDF ecryptions/sec: " + perSecond);

        /*
         * NOTE: !!! can fail on a slower system
         * 
         * On my Quad CPU Q8300, 100 repeats: 10.44/sec
         */
        assertTrue("PDF encryption too slow. !!! this can fail on a slower system !!!", perSecond > 4);
    }

    /*
     * Test the encryption of a message with a large body text (640K). A large body text is relative slow compared
     * to binary attachments
     */
    @Test
    public void testPerformanceLargeBodyText() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        Mailet mailet = new PDFEncrypt();

        String template = FileUtils.readFileToString(new File("test/resources/templates/pdf-attachment.ftl"));

        autoTransactDelegator.setProperty("test@EXAMPLE.com", "pdfTemplate", template);

        mailetConfig.setInitParameter("log", "starting");
        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("templateProperty", "pdfTemplate");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");

        mailet.init(mailetConfig);

        int repeat = 5;

        long start = System.currentTimeMillis();

        for (int i = 0; i < repeat; i++) {
            MockMail mail = new MockMail();

            mail.setState(Mail.DEFAULT);

            Passwords passwords = new Passwords();

            PasswordContainer container = new PasswordContainer("test1", "test ID");

            passwords.put("m.brinkers@pobox.com", container);

            new DjigzoMailAttributesImpl(mail).setPasswords(passwords);

            MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/test-640K.eml"));

            mail.setMessage(message);

            Collection<MailAddress> recipients = new LinkedList<MailAddress>();

            recipients.add(new MailAddress("m.bRINKERs@pobox.com"));

            mail.setRecipients(recipients);

            mail.setSender(new MailAddress("sender@example.com"));

            mailet.service(mail);

            MailUtils.validateMessage(listener.getMessages().get(0));
        }

        long diff = System.currentTimeMillis() - start;

        double perSecond = repeat * 1000.0 / diff;

        System.out.println("PDF ecryptions/sec: " + perSecond);

        /*
         * NOTE: !!! can fail on a slower system
         * 
         * On my Quad CPU Q8300, 5 repeats: 0.2/sec
         */
        assertTrue("PDF encryption too slow. !!! this can fail on a slower system !!!", perSecond > 0.1);
    }

    @Test
    public void testUserTemplateEncryptPDFSetPassThroughProcessor() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        Mailet mailet = new PDFEncrypt();

        String template = FileUtils.readFileToString(new File("test/resources/templates/pdf-attachment.ftl"));

        autoTransactDelegator.setProperty("test@EXAMPLE.com", "pdfTemplate", template);

        mailetConfig.setInitParameter("log", "starting");
        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("templateProperty", "pdfTemplate");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");
        mailetConfig.setInitParameter("passThroughProcessor", "newState");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        mail.setState(Mail.DEFAULT);

        Passwords passwords = new Passwords();

        PasswordContainer container = new PasswordContainer("pass1", "id1");

        passwords.put("m.brinkers@pobox.com", container);

        container = new PasswordContainer("pass2", "id2");

        passwords.put("123@example.com", container);

        new DjigzoMailAttributesImpl(mail).setPasswords(passwords);

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        Collection<MailAddress> recipients = new LinkedList<MailAddress>();

        recipients.add(new MailAddress("m.bRINKERs@pobox.com"));
        recipients.add(new MailAddress("123@EXAMPLE.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testUserTemplateEncryptPDF", listener.getMessages());

        assertEquals(2, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals("encryptedProcessor", listener.getStates().get(1));
        assertEquals(1, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.bRINKERs@pobox.com")));
        assertEquals(1, listener.getRecipients().get(1).size());
        assertTrue(listener.getRecipients().get(1).contains(new MailAddress("123@EXAMPLE.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals("sender@example.com", listener.getSenders().get(1).toString());
        assertEquals("newState", mail.getState());

        MimeMessage message0 = listener.getMessages().get(0);
        MimeMessage message1 = listener.getMessages().get(1);

        assertNotNull(message0);
        assertNotNull(message1);

        assertEquals("test", StringUtils.join(message0.getHeader("X-pdf-template-test")));
        assertEquals("test", StringUtils.join(message1.getHeader("X-pdf-template-test")));

        MailUtils.validateMessage(message0);
        MailUtils.validateMessage(message1);

        checkEncryption(message0, "pass1", false);
        checkEncryption(message1, "pass2", false);
    }

    @Test
    public void testEncryptPDFInvalidFrom() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "single");
        mailetConfig.setInitParameter("passThrough", "false");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/invalid-from-to-cc-reply-to.eml"));

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("123@example.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        // password is test when encrypted with password 'djigzo'
        new DjigzoMailAttributesImpl(mail).setEncryptedPassword(Base64.decodeBase64(MiscStringUtils
                .toAsciiBytes("lklfx6SWxIkAAAAQ1VTbMJjznNZjVvdggckSPQAACAAAAAAQKAxcw630UmyVhyZPiW9xhg==")));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testEncryptPDFInvalidFrom", listener.getMessages());

        assertEquals(1, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals(1, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("123@example.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals(Mail.GHOST, mail.getState());
        assertNotNull(listener.getMessages().get(0));
        assertTrue(message != listener.getMessages().get(0));

        MailUtils.validateMessage(listener.getMessages().get(0));
    }

    @Test
    public void testEncryptPDFFromPersonalUTF8() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "single");
        mailetConfig.setInitParameter("passThrough", "false");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        message.setFrom(new InternetAddress("test@example.com", "=?UTF-8?B?w6TDtsO8IMOEw5bDnA==?="));

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("m.brinkers@pobox.com"));
        recipients.add(new MailAddress("123@example.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        // password is test when encrypted with password 'djigzo'
        new DjigzoMailAttributesImpl(mail).setEncryptedPassword(Base64.decodeBase64(MiscStringUtils
                .toAsciiBytes("lklfx6SWxIkAAAAQ1VTbMJjznNZjVvdggckSPQAACAAAAAAQKAxcw630UmyVhyZPiW9xhg==")));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testEncryptPDFFromPersonalUTF8", listener.getMessages());

        assertEquals(1, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals(2, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("123@example.com")));
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.brinkers@pobox.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals(Mail.GHOST, mail.getState());
        assertNotNull(listener.getMessages().get(0));
        assertTrue(message != listener.getMessages().get(0));

        MimeMessage encrypted = listener.getMessages().get(0);

        assertTrue(encrypted.isMimeType("multipart/mixed"));

        Multipart mp = (Multipart) encrypted.getContent();

        assertEquals(2, mp.getCount());

        BodyPart messagePart = mp.getBodyPart(0);
        BodyPart pdfPart = mp.getBodyPart(1);

        assertTrue(messagePart.isMimeType("text/plain"));
        assertTrue(pdfPart.isMimeType("application/pdf"));

        // check if the body contains   (which is the decoded from personal name)
        String text = (String) messagePart.getContent();

        assertTrue(text.contains(" "));

        MailUtils.validateMessage(listener.getMessages().get(0));
    }

    @Test
    public void testSourceInvalidEncoding() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "single");
        mailetConfig.setInitParameter("passThrough", "false");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        MimeMessage message = MailUtils
                .loadMessage(new File(testBase, "mail/unknown-content-transfer-encoding.eml"));

        mail.setState("initial");
        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("m.brinkers@pobox.com"));
        recipients.add(new MailAddress("123@example.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        // password is test when encrypted with password 'djigzo'
        new DjigzoMailAttributesImpl(mail).setEncryptedPassword(Base64.decodeBase64(MiscStringUtils
                .toAsciiBytes("lklfx6SWxIkAAAAQ1VTbMJjznNZjVvdggckSPQAACAAAAAAQKAxcw630UmyVhyZPiW9xhg==")));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        assertEquals(0, listener.getMessages().size());
        assertEquals("initial", mail.getState());
        assertEquals(message, mail.getMessage());
    }

    @Test
    public void testEncryptCaseInsensitiveEmail() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        mail.setState(Mail.DEFAULT);

        Passwords passwords = new Passwords();

        PasswordContainer container = new PasswordContainer("test1", "test ID");

        passwords.put("m.brinkers@pobox.com", container);

        container = new PasswordContainer("test2", "test ID 2");

        passwords.put("123@example.com", container);

        new DjigzoMailAttributesImpl(mail).setPasswords(passwords);

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        Collection<MailAddress> recipients = new LinkedList<MailAddress>();

        recipients.add(new MailAddress("m.bRINKERs@pobox.com"));
        recipients.add(new MailAddress("123@EXAMPLE.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testEncryptPDFMultiplePasswordMode", listener.getMessages());

        assertEquals(2, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals("encryptedProcessor", listener.getStates().get(1));
        assertEquals(1, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.bRINKERs@pobox.com")));
        assertEquals(1, listener.getRecipients().get(1).size());
        assertTrue(listener.getRecipients().get(1).contains(new MailAddress("123@EXAMPLE.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals("sender@example.com", listener.getSenders().get(1).toString());
        assertEquals(Mail.DEFAULT, mail.getState());
        assertNotNull(listener.getMessages().get(0));
        assertNotNull(listener.getMessages().get(1));

        MailUtils.validateMessage(listener.getMessages().get(0));
        MailUtils.validateMessage(listener.getMessages().get(1));

        /*
         * Check if message-id was not retained
         */
        assertFalse("<111>".equals(listener.getMessages().get(0).getMessageID()));
        assertFalse("<111>".equals(listener.getMessages().get(1).getMessageID()));
    }

    @Test
    public void testRetainMessageID() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");
        mailetConfig.setInitParameter("retainMessageID", "true");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        mail.setState(Mail.DEFAULT);

        Passwords passwords = new Passwords();

        PasswordContainer container = new PasswordContainer("test1", "test ID");

        passwords.put("m.brinkers@pobox.com", container);

        container = new PasswordContainer("test2", "test ID 2");

        passwords.put("123@example.com", container);

        new DjigzoMailAttributesImpl(mail).setPasswords(passwords);

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        Collection<MailAddress> recipients = new LinkedList<MailAddress>();

        recipients.add(new MailAddress("m.bRINKERs@pobox.com"));
        recipients.add(new MailAddress("123@EXAMPLE.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testEncryptPDFMultiplePasswordMode", listener.getMessages());

        assertEquals(2, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals("encryptedProcessor", listener.getStates().get(1));
        assertEquals(1, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.bRINKERs@pobox.com")));
        assertEquals(1, listener.getRecipients().get(1).size());
        assertTrue(listener.getRecipients().get(1).contains(new MailAddress("123@EXAMPLE.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals("sender@example.com", listener.getSenders().get(1).toString());
        assertEquals(Mail.DEFAULT, mail.getState());
        assertNotNull(listener.getMessages().get(0));
        assertNotNull(listener.getMessages().get(1));

        MailUtils.validateMessage(listener.getMessages().get(0));
        MailUtils.validateMessage(listener.getMessages().get(1));

        /*
         * Check if message-id was retained
         */
        assertEquals("<111>", listener.getMessages().get(0).getMessageID());
        assertEquals("<111>", listener.getMessages().get(1).getMessageID());
    }

    @Test
    public void testEncryptPDFCloneAttributesTest() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        mail.setState(Mail.DEFAULT);

        Passwords passwords = new Passwords();

        PasswordContainer container = new PasswordContainer("test1", "test ID");

        passwords.put("m.brinkers@pobox.com", container);

        container = new PasswordContainer("test2", "test ID 2");

        passwords.put("123@example.com", container);

        new DjigzoMailAttributesImpl(mail).setPasswords(passwords);

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        mail.setAttribute("XXX", "123");
        mail.setAttribute(SMTPSession.SMTP_MAIL_EXTENSIONS_ATTRIBUTE_NAME, "AAP=NOOT");

        Collection<MailAddress> recipients = new LinkedList<MailAddress>();

        recipients.add(new MailAddress("m.brinkers@pobox.com"));
        recipients.add(new MailAddress("123@example.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testEncryptPDFMultiplePasswordMode", listener.getMessages());

        assertEquals(2, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals("encryptedProcessor", listener.getStates().get(1));
        assertEquals(1, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.brinkers@pobox.com")));
        assertEquals(1, listener.getRecipients().get(1).size());
        assertTrue(listener.getRecipients().get(1).contains(new MailAddress("123@example.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals("sender@example.com", listener.getSenders().get(1).toString());
        assertEquals(Mail.DEFAULT, mail.getState());
        assertNotNull(listener.getMessages().get(0));
        assertNotNull(listener.getMessages().get(1));

        MailUtils.validateMessage(listener.getMessages().get(0));
        MailUtils.validateMessage(listener.getMessages().get(1));

        Mail check = listener.getMails().get(0);

        assertEquals("123", check.getAttribute("XXX"));
        assertEquals("AAP=NOOT", check.getAttribute(SMTPSession.SMTP_MAIL_EXTENSIONS_ATTRIBUTE_NAME));
    }

    @Test
    public void testEncryptPDFMultiplePasswordMode() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        mail.setState(Mail.DEFAULT);

        Passwords passwords = new Passwords();

        PasswordContainer container = new PasswordContainer("test1", "test ID");

        passwords.put("m.brinkers@pobox.com", container);

        container = new PasswordContainer("test2", "test ID 2");

        passwords.put("123@example.com", container);

        new DjigzoMailAttributesImpl(mail).setPasswords(passwords);

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        Collection<MailAddress> recipients = new LinkedList<MailAddress>();

        recipients.add(new MailAddress("m.brinkers@pobox.com"));
        recipients.add(new MailAddress("123@example.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testEncryptPDFMultiplePasswordMode", listener.getMessages());

        assertEquals(2, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals("encryptedProcessor", listener.getStates().get(1));
        assertEquals(1, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.brinkers@pobox.com")));
        assertEquals(1, listener.getRecipients().get(1).size());
        assertTrue(listener.getRecipients().get(1).contains(new MailAddress("123@example.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals("sender@example.com", listener.getSenders().get(1).toString());
        assertEquals(Mail.DEFAULT, mail.getState());
        assertNotNull(listener.getMessages().get(0));
        assertNotNull(listener.getMessages().get(1));

        MailUtils.validateMessage(listener.getMessages().get(0));
        MailUtils.validateMessage(listener.getMessages().get(1));
    }

    @Test
    public void testEncryptPDFMultiplePasswordModeMissingPasswords() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        mail.setState(Mail.DEFAULT);

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("m.brinkers@pobox.com"));
        recipients.add(new MailAddress("123@example.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testEncryptPDFMultiplePasswordModeMissingPasswords",
                listener.getMessages());

        assertEquals(1, listener.getMessages().size());
        assertEquals("notEncryptedProcessor", listener.getStates().get(0));
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("123@example.com")));
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.brinkers@pobox.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals(Mail.DEFAULT, mail.getState());
        assertNotNull(listener.getMessages().get(0));

        MailUtils.validateMessage(listener.getMessages().get(0));
    }

    @Test
    public void testEncryptPDFSinglePasswordMode() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "single");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        Collection<MailAddress> recipients = new LinkedList<MailAddress>();

        recipients.add(new MailAddress("m.brinkers@pobox.com"));
        recipients.add(new MailAddress("123@example.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        // password is test when encrypted with password 'djigzo'
        new DjigzoMailAttributesImpl(mail).setEncryptedPassword(Base64.decodeBase64(MiscStringUtils
                .toAsciiBytes("lklfx6SWxIkAAAAQ1VTbMJjznNZjVvdggckSPQAACAAAAAAQKAxcw630UmyVhyZPiW9xhg==")));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testEncryptPDFSinglePasswordMode", listener.getMessages());

        assertEquals(1, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals(2, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("123@example.com")));
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.brinkers@pobox.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertNull(mail.getState());
        assertNotNull(listener.getMessages().get(0));
        assertTrue(message != listener.getMessages().get(0));

        assertEquals("<test@example.com>", listener.getMessages().get(0).getHeader("from", ","));
        assertEquals("<test@example.com>", listener.getMessages().get(0).getHeader("to", ","));
        assertEquals("normal message with attachment", listener.getMessages().get(0).getHeader("subject", ","));
        assertEquals("1.0", listener.getMessages().get(0).getHeader("MIME-Version", ","));
        assertEquals("3", listener.getMessages().get(0).getHeader("X-Priority", ","));
        assertEquals("Normal", listener.getMessages().get(0).getHeader("X-MSMail-Priority", ","));
        assertEquals("Produced By Microsoft MimeOLE V6.00.2800.1896",
                listener.getMessages().get(0).getHeader("X-MimeOLE", ","));
        assertEquals("test 1,test 2", listener.getMessages().get(0).getHeader("X-Test", ","));
        assertEquals("test 3", listener.getMessages().get(0).getHeader("X-Test-a", ","));
        assertEquals("test 4", listener.getMessages().get(0).getHeader("X-Test-b", ","));

        MailUtils.validateMessage(listener.getMessages().get(0));
    }

    @Test
    public void testEncryptPDFSinglePasswordModeWithPasswordID() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf-sms.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "single");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("m.brinkers@pobox.com"));
        recipients.add(new MailAddress("123@example.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        // password is test when encrypted with password 'djigzo'
        new DjigzoMailAttributesImpl(mail).setEncryptedPassword(Base64.decodeBase64(MiscStringUtils
                .toAsciiBytes("lklfx6SWxIkAAAAQ1VTbMJjznNZjVvdggckSPQAACAAAAAAQKAxcw630UmyVhyZPiW9xhg==")));

        new DjigzoMailAttributesImpl(mail).setPasswordID("1234");

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testEncryptPDFSinglePasswordModeWithPasswordID", listener.getMessages());

        assertEquals(1, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals(2, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("123@example.com")));
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.brinkers@pobox.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertNull(mail.getState());
        assertNotNull(listener.getMessages().get(0));
        assertTrue(message != listener.getMessages().get(0));

        MailUtils.validateMessage(listener.getMessages().get(0));
    }

    @Test
    public void testEncryptPDFSinglePasswordModeMissingPassword() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "single");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        mail.setState(Mail.DEFAULT);

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        Collection<MailAddress> recipients = new LinkedList<MailAddress>();

        recipients.add(new MailAddress("m.brinkers@pobox.com"));
        recipients.add(new MailAddress("123@example.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testEncryptPDFSinglePasswordModeMissingPassword", listener.getMessages());

        assertEquals(1, listener.getMessages().size());
        assertEquals("notEncryptedProcessor", listener.getStates().get(0));
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("123@example.com")));
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.brinkers@pobox.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals(Mail.DEFAULT, mail.getState());
        assertNotNull(listener.getMessages().get(0));

        MailUtils.validateMessage(listener.getMessages().get(0));
    }

    @Test
    public void testEncryptPDFSinglePasswordModeNoPassthrough() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "single");
        mailetConfig.setInitParameter("passThrough", "false");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("m.brinkers@pobox.com"));
        recipients.add(new MailAddress("123@example.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        // password is test when encrypted with password 'djigzo'
        new DjigzoMailAttributesImpl(mail).setEncryptedPassword(Base64.decodeBase64(MiscStringUtils
                .toAsciiBytes("lklfx6SWxIkAAAAQ1VTbMJjznNZjVvdggckSPQAACAAAAAAQKAxcw630UmyVhyZPiW9xhg==")));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testEncryptPDFSinglePasswordModeNoPassthrough", listener.getMessages());

        assertEquals(1, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals(2, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("123@example.com")));
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.brinkers@pobox.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals(Mail.GHOST, mail.getState());
        assertNotNull(listener.getMessages().get(0));
        assertTrue(message != listener.getMessages().get(0));

        MailUtils.validateMessage(listener.getMessages().get(0));
    }

    @Test
    public void testUserTemplateEncryptPDF() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        Mailet mailet = new PDFEncrypt();

        String template = FileUtils.readFileToString(new File("test/resources/templates/pdf-attachment.ftl"));

        autoTransactDelegator.setProperty("test@EXAMPLE.com", "pdfTemplate", template);

        mailetConfig.setInitParameter("log", "starting");
        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("templateProperty", "pdfTemplate");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        mail.setState(Mail.DEFAULT);

        Passwords passwords = new Passwords();

        PasswordContainer container = new PasswordContainer("test1", "test ID");

        passwords.put("m.brinkers@pobox.com", container);

        container = new PasswordContainer("test2", "test ID 2");

        passwords.put("123@example.com", container);

        new DjigzoMailAttributesImpl(mail).setPasswords(passwords);

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        Collection<MailAddress> recipients = new LinkedList<MailAddress>();

        recipients.add(new MailAddress("m.bRINKERs@pobox.com"));
        recipients.add(new MailAddress("123@EXAMPLE.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testUserTemplateEncryptPDF", listener.getMessages());

        assertEquals(2, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals("encryptedProcessor", listener.getStates().get(1));
        assertEquals(1, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.bRINKERs@pobox.com")));
        assertEquals(1, listener.getRecipients().get(1).size());
        assertTrue(listener.getRecipients().get(1).contains(new MailAddress("123@EXAMPLE.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals("sender@example.com", listener.getSenders().get(1).toString());
        assertEquals(Mail.DEFAULT, mail.getState());

        MimeMessage message0 = listener.getMessages().get(0);
        MimeMessage message1 = listener.getMessages().get(1);

        assertNotNull(message0);
        assertNotNull(message1);

        assertEquals("test", StringUtils.join(message0.getHeader("X-pdf-template-test")));
        assertEquals("test", StringUtils.join(message1.getHeader("X-pdf-template-test")));

        MailUtils.validateMessage(listener.getMessages().get(0));
        MailUtils.validateMessage(listener.getMessages().get(1));
    }

    @Test
    public void testUserTemplateEncryptPDFNoTemplateProperty() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        Mailet mailet = new PDFEncrypt();

        String template = FileUtils.readFileToString(new File("test/resources/templates/pdf-attachment.ftl"));

        autoTransactDelegator.setProperty("someOtherUser@EXAMPLE.com", "pdfTemplate", template);

        mailetConfig.setInitParameter("log", "starting");
        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("templateProperty", "pdfTemplate");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        mail.setState(Mail.DEFAULT);

        Passwords passwords = new Passwords();

        PasswordContainer container = new PasswordContainer("test1", "test ID");

        passwords.put("m.brinkers@pobox.com", container);

        container = new PasswordContainer("test2", "test ID 2");

        passwords.put("123@example.com", container);

        new DjigzoMailAttributesImpl(mail).setPasswords(passwords);

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/normal-message-with-attach.eml"));

        mail.setMessage(message);

        Collection<MailAddress> recipients = new LinkedList<MailAddress>();

        recipients.add(new MailAddress("m.bRINKERs@pobox.com"));
        recipients.add(new MailAddress("123@EXAMPLE.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testUserTemplateEncryptPDFNoTemplateProperty", listener.getMessages());

        assertEquals(2, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
        assertEquals("encryptedProcessor", listener.getStates().get(1));
        assertEquals(1, listener.getRecipients().get(0).size());
        assertTrue(listener.getRecipients().get(0).contains(new MailAddress("m.bRINKERs@pobox.com")));
        assertEquals(1, listener.getRecipients().get(1).size());
        assertTrue(listener.getRecipients().get(1).contains(new MailAddress("123@EXAMPLE.com")));
        assertEquals("sender@example.com", listener.getSenders().get(0).toString());
        assertEquals("sender@example.com", listener.getSenders().get(1).toString());
        assertEquals(Mail.DEFAULT, mail.getState());

        MimeMessage message0 = listener.getMessages().get(0);
        MimeMessage message1 = listener.getMessages().get(1);

        assertNotNull(message0);
        assertNotNull(message1);

        assertNull(message0.getHeader("X-pdf-template-test"));
        assertNull(message1.getHeader("X-pdf-template-test"));

        MailUtils.validateMessage(listener.getMessages().get(0));
        MailUtils.validateMessage(listener.getMessages().get(1));
    }

    @Test
    public void testEncryptPDFInvalidContentType() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        PDFEncrypt mailet = new PDFEncrypt();

        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "single");
        mailetConfig.setInitParameter("passThrough", "false");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        MimeMessage message = MailUtils
                .loadMessage(new File(testBase, "mail/pdf-attachment-faulty-content-type.eml"));

        mail.setMessage(message);

        Set<MailAddress> recipients = new HashSet<MailAddress>();

        recipients.add(new MailAddress("123@example.com"));

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("sender@example.com"));

        // password is test when encrypted with password 'djigzo'
        new DjigzoMailAttributesImpl(mail).setEncryptedPassword(Base64.decodeBase64(MiscStringUtils
                .toAsciiBytes("lklfx6SWxIkAAAAQ1VTbMJjznNZjVvdggckSPQAACAAAAAAQKAxcw630UmyVhyZPiW9xhg==")));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testEncryptPDFInvalidContentType", listener.getMessages());

        assertEquals(1, listener.getMessages().size());
        assertEquals("encryptedProcessor", listener.getStates().get(0));
    }

    /*
     * Test for https://jira.djigzo.com/browse/GATEWAY-38
     */
    @Test
    public void testBug38() throws Exception {
        MockMailetConfig mailetConfig = new MockMailetConfig("test");

        SendMailEventListenerImpl listener = new SendMailEventListenerImpl();

        mailetConfig.getMailetContext().setSendMailEventListener(listener);

        Mailet mailet = new PDFEncrypt();

        String template = FileUtils
                .readFileToString(new File("test/resources/templates/encrypted-pdf-otp-bug38.ftl"));

        autoTransactDelegator.setProperty("test@example.com", "pdfTemplate", template);

        mailetConfig.setInitParameter("log", "starting");
        mailetConfig.setInitParameter("template", "encrypted-pdf.ftl");
        mailetConfig.setInitParameter("templateProperty", "pdfTemplate");
        mailetConfig.setInitParameter("encryptedProcessor", "encryptedProcessor");
        mailetConfig.setInitParameter("notEncryptedProcessor", "notEncryptedProcessor");
        mailetConfig.setInitParameter("passwordMode", "multiple");

        mailet.init(mailetConfig);

        MockMail mail = new MockMail();

        mail.setState(Mail.DEFAULT);

        int recipientCount = 10;

        Passwords passwords = new Passwords();

        Collection<MailAddress> recipients = new LinkedList<MailAddress>();

        for (int i = 0; i < recipientCount; i++) {
            String recipient = "test" + i + "@example.com";

            PasswordContainer container = new PasswordContainer("test" + i, "ID" + i);

            passwords.put(recipient, container);

            recipients.add(new MailAddress(recipient));
        }

        new DjigzoMailAttributesImpl(mail).setPasswords(passwords);

        MimeMessage message = MailUtils.loadMessage(new File(testBase, "mail/simple-text-message.eml"));

        mail.setMessage(message);

        mail.setRecipients(recipients);

        mail.setSender(new MailAddress("test@example.com"));

        mailet.service(mail);

        MailUtils.validateMessage(mail.getMessage());

        TestUtils.saveMessages(tempDir, "testBug38", listener.getMessages());

        assertEquals(recipientCount, listener.getMessages().size());

        for (int i = 0; i < recipientCount; i++) {
            Collection<?> pdfRecipients = listener.getRecipients().get(i);

            assertEquals(1, pdfRecipients.size());

            String pdfRecipient = pdfRecipients.iterator().next().toString();

            assertEquals("test" + i + "@example.com", pdfRecipient);

            message = listener.getMessages().get(i);

            String body = BodyPartUtils.getPlainBody(message);

            assertTrue(body.contains("Recipient: test" + i + "%40example.com"));
            assertTrue(body.contains("Recipient: test" + i + "%40example.com"));
        }
    }
}