Package com.consol.citrus.mail.server

Source Code of com.consol.citrus.mail.server.MailServer

/*
* Copyright 2006-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.consol.citrus.mail.server;

import com.consol.citrus.exceptions.CitrusRuntimeException;
import com.consol.citrus.mail.client.MailEndpointConfiguration;
import com.consol.citrus.mail.message.CitrusMailMessageHeaders;
import com.consol.citrus.mail.message.MailMessageConverter;
import com.consol.citrus.mail.model.*;
import com.consol.citrus.message.DefaultMessage;
import com.consol.citrus.message.Message;
import com.consol.citrus.server.AbstractServer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.mail.javamail.MimeMailMessage;
import org.subethamail.smtp.RejectException;
import org.subethamail.smtp.helper.SimpleMessageListener;
import org.subethamail.smtp.helper.SimpleMessageListenerAdapter;
import org.subethamail.smtp.server.SMTPServer;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import java.io.InputStream;
import java.util.*;

/**
* Mail server implementation starts new SMTP server instance and listens for incoming mail messages. Incoming mail messages
* are converted to XML representation and forwarded to some message endpoint adapter (e.g. forwarding mail content to
* a message channel).
*
* By default incoming messages are accepted automatically. When auto accept is disabled the endpoint adapter is invoked with
* accept request and test case has to decide accept outcome in response.
*
* In case of incoming multipart mail messages the server is able to split the body parts into separate XML messages
* handled by the endpoint adapter.
*
* @author Christoph Deppisch
* @since 1.4
*/
public class MailServer extends AbstractServer implements SimpleMessageListener, InitializingBean {

    /** Server port */
    private int port = 25;

    /** XML message mapper */
    private MailMessageMapper mailMessageMapper = new MailMessageMapper();

    /** Mail message converter */
    private MailMessageConverter messageConverter = new MailMessageConverter();

    /** Java mail session */
    private Session mailSession;

    /** Java mail properties */
    private Properties javaMailProperties = new Properties();

    /** Should accept automatically or handled via test case */
    private boolean autoAccept = true;

    /** Should split multipart messages for each mime part */
    private boolean splitMultipart = false;

    /** Smtp server instance */
    private SMTPServer smtpServer;

    @Override
    protected void startup() {
        smtpServer = new SMTPServer(new SimpleMessageListenerAdapter(this));
        smtpServer.setSoftwareName(getName());
        smtpServer.setPort(port);
        smtpServer.start();
    }

    @Override
    protected void shutdown() {
        smtpServer.stop();
    }

    @Override
    public boolean accept(String from, String recipient) {
        if (autoAccept) {
            return true;
        }

        Message response = getEndpointAdapter().handleMessage(
                new DefaultMessage(mailMessageMapper.toXML(createAcceptRequest(from, recipient))));

        if (response == null || response.getPayload() == null) {
            throw new CitrusRuntimeException("Did not receive accept response. Missing accept response because autoAccept is disabled.");
        }

        AcceptResponse acceptResponse = null;
        if (response.getPayload() instanceof AcceptResponse) {
            acceptResponse = (AcceptResponse) response.getPayload();
        } else if (response.getPayload() instanceof String) {
            acceptResponse = (AcceptResponse) mailMessageMapper.fromXML(response.getPayload().toString());
        }

        if (acceptResponse == null) {
            throw new CitrusRuntimeException("Unable to read accept response from paylaod: " + response);
        }

        return acceptResponse.isAccept();
    }

    @Override
    public void deliver(String from, String recipient, InputStream data) {
        try {
            MimeMailMessage mimeMailMessage = new MimeMailMessage(new MimeMessage(getSession(), data));
            Message request = messageConverter.convertInbound(mimeMailMessage, getEndpointConfiguration());
            Message response = invokeEndpointAdapter(request);

            if (response != null && response.getPayload() != null) {
                MailMessageResponse mailResponse = null;
                if (response.getPayload() instanceof MailMessageResponse) {
                    mailResponse = (MailMessageResponse) response.getPayload();
                } else if (response.getPayload() instanceof String) {
                    mailResponse = (MailMessageResponse) mailMessageMapper.fromXML(response.getPayload().toString());
                }

                if (mailResponse != null && mailResponse.getCode() != MailMessageResponse.OK_CODE) {
                    throw new RejectException(mailResponse.getCode(), mailResponse.getMessage());
                }
            }
        } catch (MessagingException e) {
            throw new CitrusRuntimeException(e);
        }
    }

    /**
     * Invokes the endpoint adapter with constructed mail message and headers.
     * @param request
     */
    protected Message invokeEndpointAdapter(Message request) {
        MailMessage mailMessage = (MailMessage) request.getPayload();

        if (splitMultipart) {
            return split(mailMessage.getBody(), request.copyHeaders());
        } else {
            return getEndpointAdapter().handleMessage(new DefaultMessage(mailMessageMapper.toXML(mailMessage), request.copyHeaders()));
        }
    }

    /**
     * Split mail message into several messages. Each body and each attachment results in separate message
     * invoked on endpoint adapter. Mail message response if any should be sent only once within test case.
     * However latest mail response sent by test case is returned, others are ignored.
     *
     * @param bodyPart
     * @param messageHeaders
     */
    private Message split(BodyPart bodyPart, Map<String, Object> messageHeaders) {
        MailMessage mailMessage = createMailMessage(messageHeaders);
        mailMessage.setBody(new BodyPart(bodyPart.getContent(), bodyPart.getContentType()));

        Stack<Message> responseStack = new Stack<Message>();
        if (bodyPart instanceof AttachmentPart) {
            fillStack(getEndpointAdapter().handleMessage(new DefaultMessage(mailMessageMapper.toXML(mailMessage), messageHeaders)
                    .setHeader(CitrusMailMessageHeaders.MAIL_CONTENT_TYPE, bodyPart.getContentType())
                    .setHeader(CitrusMailMessageHeaders.MAIL_FILENAME, ((AttachmentPart) bodyPart).getFileName())), responseStack);
        } else {
            fillStack(getEndpointAdapter().handleMessage(new DefaultMessage(mailMessageMapper.toXML(mailMessage), messageHeaders)
                    .setHeader(CitrusMailMessageHeaders.MAIL_CONTENT_TYPE, bodyPart.getContentType())), responseStack);
        }

        if (bodyPart.hasAttachments()) {
            for (AttachmentPart attachmentPart : bodyPart.getAttachments()) {
                fillStack(split(attachmentPart, messageHeaders), responseStack);
            }
        }

        return responseStack.isEmpty() ? null : responseStack.pop();
    }

    private void fillStack(Message message, Stack<Message> responseStack) {
        if (message != null) {
            responseStack.push(message);
        }
    }

    /**
     * Creates a new mail message model object from message headers.
     * @param messageHeaders
     * @return
     */
    protected MailMessage createMailMessage(Map<String, Object> messageHeaders) {
        MailMessage message = new MailMessage();
        message.setFrom(messageHeaders.get(CitrusMailMessageHeaders.MAIL_FROM).toString());
        message.setTo(messageHeaders.get(CitrusMailMessageHeaders.MAIL_TO).toString());
        message.setCc(messageHeaders.get(CitrusMailMessageHeaders.MAIL_CC).toString());
        message.setBcc(messageHeaders.get(CitrusMailMessageHeaders.MAIL_BCC).toString());
        message.setSubject(messageHeaders.get(CitrusMailMessageHeaders.MAIL_SUBJECT).toString());
        return message;
    }

    private AcceptRequest createAcceptRequest(String from, String recipient) {
        return new AcceptRequest(from, recipient);
    }

    @Override
    public MailEndpointConfiguration getEndpointConfiguration() {
        MailEndpointConfiguration endpointConfiguration = new MailEndpointConfiguration();
        endpointConfiguration.setMessageConverter(messageConverter);
        endpointConfiguration.setMailMessageMapper(mailMessageMapper);
        endpointConfiguration.setJavaMailProperties(javaMailProperties);

        return endpointConfiguration;
    }

    /**
     * Return new mail session if not already created before.
     * @return
     */
    public synchronized Session getSession() {
        if (this.mailSession == null) {
            this.mailSession = Session.getInstance(this.javaMailProperties);
        }
        return this.mailSession;
    }

    /**
     * Is auto accept enabled.
     * @return
     */
    public boolean isAutoAccept() {
        return autoAccept;
    }

    /**
     * Enable/disable auto accept feature.
     * @param autoAccept
     */
    public void setAutoAccept(boolean autoAccept) {
        this.autoAccept = autoAccept;
    }

    /**
     * Gets the mail message mapper.
     * @return
     */
    public MailMessageMapper getMailMessageMapper() {
        return mailMessageMapper;
    }

    /**
     * Sets the mail message mapper.
     * @param mailMessageMapper
     */
    public void setMailMessageMapper(MailMessageMapper mailMessageMapper) {
        this.mailMessageMapper = mailMessageMapper;
    }

    /**
     * Gets the Java mail properties.
     * @return
     */
    public Properties getJavaMailProperties() {
        return javaMailProperties;
    }

    /**
     * Sets the Java mail properties.
     * @param javaMailProperties
     */
    public void setJavaMailProperties(Properties javaMailProperties) {
        this.javaMailProperties = javaMailProperties;
    }

    /**
     * Gets the server port.
     * @return
     */
    public int getPort() {
        return port;
    }

    /**
     * Sets the server port.
     * @param port
     */
    public void setPort(int port) {
        this.port = port;
    }

    /**
     * Gets the smtp server instance.
     * @return
     */
    public SMTPServer getSmtpServer() {
        return smtpServer;
    }

    /**
     * Sets the smtp server instance.
     * @param smtpServer
     */
    public void setSmtpServer(SMTPServer smtpServer) {
        this.smtpServer = smtpServer;
    }

    /**
     * Gets the split multipart message.
     * @return
     */
    public boolean isSplitMultipart() {
        return splitMultipart;
    }

    /**
     * Sets the split multipart message.
     * @param splitMultipart
     */
    public void setSplitMultipart(boolean splitMultipart) {
        this.splitMultipart = splitMultipart;
    }

    /**
     * Gets the message converter.
     * @return
     */
    public MailMessageConverter getMessageConverter() {
        return messageConverter;
    }

    /**
     * Sets the message converter.
     * @param messageConverter
     */
    public void setMessageConverter(MailMessageConverter messageConverter) {
        this.messageConverter = messageConverter;
    }
}
TOP

Related Classes of com.consol.citrus.mail.server.MailServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.