You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@jakarta.apache.org by se...@apache.org on 2010/07/01 16:34:35 UTC

svn commit: r959681 [2/2] - in /jakarta/jmeter/trunk: docs/images/screenshots/ src/core/org/apache/jmeter/resources/ src/protocol/mail/org/apache/jmeter/protocol/smtp/ src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/ src/protocol/mail/org/apa...

Added: jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/SendMailCommand.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/SendMailCommand.java?rev=959681&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/SendMailCommand.java (added)
+++ jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/SendMailCommand.java Thu Jul  1 14:34:35 2010
@@ -0,0 +1,767 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jmeter.protocol.smtp.sampler.protocol;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.security.Security;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Vector;
+
+import javax.activation.DataHandler;
+import javax.activation.FileDataSource;
+import javax.mail.BodyPart;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+import org.apache.jmeter.services.FileServer;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.log.Logger;
+
+/**
+ * This class performs all tasks necessary to send a message (build message,
+ * prepare connection, send message). Provides getter-/setter-methods for an
+ * SmtpSampler-object to configure transport and message settings. The
+ * send-mail-command itself is started by the SmtpSampler-object.
+ */
+public class SendMailCommand {
+
+    /**
+     * Standard-Constructor
+     */
+    public SendMailCommand() {
+        headers = new HashMap<String, String>();
+        attachments = new Vector<File>();
+    }
+
+    // local vars
+    private static final Logger logger = LoggingManager.getLoggerForClass();
+    public static final String TRUST_ALL_SOCKET_FACTORY = "jmeter.smtpsampler.protocol.TrustAllSSLSocketFactory";
+
+    private boolean useSSL = false;
+    private boolean useStartTLS = false;
+    private boolean trustAllCerts = false;
+    private boolean enforceStartTLS = false;
+    private boolean startTLSSuccessful = false;
+    private boolean sendEmlMessage = false;
+    private String smtpServer;
+    private String smtpPort;
+    private String sender;
+    private String emlMessage;
+    private List<InternetAddress> receiverTo;
+    private List<InternetAddress> receiverCC;
+    private List<InternetAddress> receiverBCC;
+    private HashMap<String, String> headers;
+    private String subject = "";
+
+    private boolean useAuthentication = false;
+    private String username;
+    private String password;
+
+    private boolean useLocalTrustStore;
+    private String trustStoreToUse;
+
+    private List<File> attachments;
+
+    private MailBodyProvider mbProvider;
+
+    // needed to check starttls functionality
+    private PrintStream debugOutStream;
+    private BufferedReader debugReader;
+
+    // case we are measuring real time of spedition
+    private boolean synchronousMode;
+
+    private Session session;
+    private Message message;
+
+    private StringBuffer serverResponse = new StringBuffer();
+
+    /**
+     * Prepares message prior to be sent via execute()-method, i.e. sets
+     * properties such as protocol, authentication, etc.
+     *
+     * @return Message-object to be sent to execute()-method
+     * @throws MessagingException 
+     * @throws IOException 
+     */
+    public Message prepareMessage() throws MessagingException, IOException {
+
+        java.util.Properties props = new java.util.Properties();
+
+        String protocol = getProtocol();
+
+        // set properties using JAF
+        props.put("mail." + protocol + ".host", smtpServer);
+        props.put("mail." + protocol + ".port", smtpPort);
+        props.put("mail." + protocol + ".auth", Boolean
+                .toString(useAuthentication));
+        // props.put("mail.debug","true");
+
+        if (useStartTLS) {
+            props.put("mail.smtp.starttls.enable", "true");
+            //props.put("mail.debug", "true");
+        }
+
+        if (trustAllCerts && protocol.equalsIgnoreCase("smtps")) {
+            props.setProperty("mail.smtps.socketFactory.class",
+                    TRUST_ALL_SOCKET_FACTORY);
+            props.setProperty("mail.smtps.socketFactory.fallback", "false");
+        }
+
+        session = Session.getInstance(props, null);
+
+        if (sendEmlMessage) {
+            message = new MimeMessage(session, new FileInputStream(emlMessage));
+        } else {
+            message = new MimeMessage(session);
+            // handle body and attachments
+            Multipart multipart = new MimeMultipart();
+            BodyPart body = new MimeBodyPart();
+            body.setText(mbProvider.getMailBody());
+            multipart.addBodyPart(body);
+
+            for (File f : attachments) {
+                BodyPart attach = new MimeBodyPart();
+                attach.setFileName(f.getName());
+                attach.setDataHandler(new DataHandler(new FileDataSource(f)));
+                multipart.addBodyPart(attach);
+            }
+
+            message.setContent(multipart);
+        }
+
+        // set from field and subject
+        if (null != sender) {
+            message.setFrom(new InternetAddress(sender));
+        }
+        if (null != subject) {
+            message.setSubject(subject);
+        }
+
+        if (receiverTo != null) {
+            InternetAddress[] to = new InternetAddress[receiverTo.size()];
+            receiverTo.toArray(to);
+            message.setRecipients(Message.RecipientType.TO, to);
+        }
+
+        if (receiverCC != null) {
+
+            InternetAddress[] cc = new InternetAddress[receiverCC.size()];
+            receiverCC.toArray(cc);
+            message.setRecipients(Message.RecipientType.CC, cc);
+        }
+
+        if (receiverBCC != null) {
+            InternetAddress[] bcc = new InternetAddress[receiverBCC.size()];
+            receiverBCC.toArray(bcc);
+            message.setRecipients(Message.RecipientType.BCC, bcc);
+        }
+
+        for (String key : headers.keySet()) {
+            message.setHeader(key, headers.get(key));
+        }
+
+        message.saveChanges();
+        return message;
+    }
+
+    /**
+     * Sends message to mailserver, including all necessary tasks. Contains 2
+     * ugly hacks to ensure the use of StartTLS if needed (see comments "UGLY
+     * HACK X") where logfiles are monitored
+     *
+     * @param message
+     *            Message prior prepared by prepareMessage()
+     * @throws Exception
+     */
+    public void execute(Message message) throws Exception {
+
+        System.clearProperty("javax.net.ssl.trustStore");
+
+        if (useLocalTrustStore) {
+            File truststore = new File(trustStoreToUse);
+            logger.info("load local truststore - try to load truststore from: "+truststore.getAbsolutePath());
+            if(!truststore.exists()){
+                logger.info("load local truststore -Failed to load truststore from: "+truststore.getAbsolutePath());
+                truststore = new File(FileServer.getFileServer().getBaseDir(), trustStoreToUse);
+                logger.info("load local truststore -Attempting to read truststore from:  "+truststore.getAbsolutePath());
+                if(!truststore.exists()){
+                    logger.info("load local truststore -Failed to load truststore from: "+truststore.getAbsolutePath() + ". Local truststore not available, aborting execution.");
+                    throw new IOException("Local truststore file not found. Also not available under : " + truststore.getAbsolutePath());
+                }
+            }
+            System.setProperty("javax.net.ssl.trustStore", truststore.getAbsolutePath());
+        }
+
+        /*
+         * UGLY HACK 1: redirect session-DebugOutput to ensure
+         * StartTLS-Support
+         */
+        ByteArrayOutputStream debugOutputStream = new ByteArrayOutputStream();
+        debugOutStream = new PrintStream(debugOutputStream);
+        session.setDebugOut(debugOutStream);
+        session.setDebug(true);
+
+        Transport tr = session.getTransport(getProtocol());
+        SynchronousTransportListener listener = null;
+
+        if (synchronousMode) {
+            listener = new SynchronousTransportListener();
+            tr.addTransportListener(listener);
+        }
+
+        if (useAuthentication) {
+            tr.connect(smtpServer, username, password);
+        } else {
+            tr.connect();
+        }
+
+        tr.sendMessage(message, message.getAllRecipients());
+
+        if (synchronousMode) {
+            listener.attend();
+        }
+
+        tr.close();
+        logger.debug("transport closed");
+
+        /*
+         * UGLY HACK 2: read from redirected debug-output
+         */
+        debugOutStream.flush();
+        debugReader = new BufferedReader(new InputStreamReader(
+                new ByteArrayInputStream(debugOutputStream.toByteArray())));
+        String line;
+        int i = 0;
+        while ((line = debugReader.readLine()) != null) {
+            logger.debug("server line " + i + ": " + line);
+            // unusable for the astf runs bom
+            //serverResponse.append(line);
+            //serverResponse.append("\n");
+            if (line.matches(".*Ready to start TLS.*")) {
+                if (useStartTLS && enforceStartTLS) {
+                    startTLSSuccessful = true;
+                }
+            }
+        }
+        debugReader.close();
+        debugOutStream.close();
+        session.setDebugOut(System.out);
+        if (useStartTLS && enforceStartTLS) {
+            if (!startTLSSuccessful) {
+                throw new MessagingException("StartTLS failed");
+            }
+        }
+
+        logger.debug("message sent");
+        return;
+    }
+
+    /**
+     * Processes prepareMessage() and execute()
+     *
+     * @throws Exception
+     */
+    public void execute() throws Exception {
+        execute(prepareMessage());
+    }
+
+    /**
+     * Returns FQDN or IP of SMTP-server to be used to send message - standard
+     * getter
+     *
+     * @return FQDN or IP of SMTP-server
+     */
+    public String getSmtpServer() {
+        return smtpServer;
+    }
+
+    /**
+     * Sets FQDN or IP of SMTP-server to be used to send message - to be called
+     * by SmtpSampler-object
+     *
+     * @param smtpServer
+     *            FQDN or IP of SMTP-server
+     */
+    public void setSmtpServer(String smtpServer) {
+        this.smtpServer = smtpServer;
+    }
+
+    /**
+     * Returns sender-address for current message - standard getter
+     *
+     * @return sender-address
+     */
+    public String getSender() {
+        return sender;
+    }
+
+    /**
+     * Sets the sender-address for the current message - to be called by
+     * SmtpSampler-object
+     *
+     * @param sender
+     *            Sender-address for current message
+     */
+    public void setSender(String sender) {
+        this.sender = sender;
+    }
+
+    /**
+     * Returns subject for current message - standard getter
+     *
+     * @return Subject of current message
+     */
+    public String getSubject() {
+        return subject;
+    }
+
+    /**
+     * Sets subject for current message - called by SmtpSampler-object
+     *
+     * @param subject
+     *            Subject for message of current message
+     */
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+    /**
+     * Returns MailBodyProvider-Object for currend message
+     *
+     * @see MailBodyProvider
+     * @return Current MailBody-Provider-Object
+     */
+    public MailBodyProvider getMbProvider() {
+        return mbProvider;
+    }
+
+    /**
+     * Sets MailBodyProvider-Object for currend message - to be called by
+     * SmtpSampler-object
+     *
+     * @see MailBodyProvider
+     * @param mbProvider
+     *            MailBody-Provider to be used
+     */
+    public void setMbProvider(MailBodyProvider mbProvider) {
+        this.mbProvider = mbProvider;
+    }
+
+    /**
+     * Returns username to authenticate at the mailserver - standard getter
+     *
+     * @return Username for mailserver
+     */
+    public String getUsername() {
+        return username;
+    }
+
+    /**
+     * Sets username to authenticate at the mailserver - to be called by
+     * SmtpSampler-object
+     *
+     * @param username
+     *            Username for mailserver
+     */
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    /**
+     * Returns password to authenticate at the mailserver - standard getter
+     *
+     * @return Password for mailserver
+     */
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * Sets password to authenticate at the mailserver - to be called by
+     * SmtpSampler-object
+     *
+     * @param password
+     *            Password for mailserver
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    /**
+     * Returns receivers of current message <InternetAddress> ("to") - standard
+     * getter
+     *
+     * @return List of receivers
+     */
+    public List<InternetAddress> getReceiverTo() {
+        return receiverTo;
+    }
+
+    /**
+     * Sets receivers of current message ("to") - to be called by
+     * SmtpSampler-object
+     *
+     * @param receiverTo
+     *            List of receivers <InternetAddress>
+     */
+    public void setReceiverTo(List<InternetAddress> receiverTo) {
+        this.receiverTo = receiverTo;
+    }
+
+    /**
+     * Returns receivers of current message <InternetAddress> ("cc") - standard
+     * getter
+     *
+     * @return List of receivers
+     */
+    public List<InternetAddress> getReceiverCC() {
+        return receiverCC;
+    }
+
+    /**
+     * Sets receivers of current message ("cc") - to be called by
+     * SmtpSampler-object
+     *
+     * @param receiverCC
+     *            List of receivers <InternetAddress>
+     */
+    public void setReceiverCC(List<InternetAddress> receiverCC) {
+        this.receiverCC = receiverCC;
+    }
+
+    /**
+     * Returns receivers of current message <InternetAddress> ("bcc") - standard
+     * getter
+     *
+     * @return List of receivers
+     */
+    public List<InternetAddress> getReceiverBCC() {
+        return receiverBCC;
+    }
+
+    /**
+     * Sets receivers of current message ("bcc") - to be called by
+     * SmtpSampler-object
+     *
+     * @param receiverBCC
+     *            List of receivers <InternetAddress>
+     */
+    public void setReceiverBCC(List<InternetAddress> receiverBCC) {
+        this.receiverBCC = receiverBCC;
+    }
+
+    /**
+     * Returns if authentication is used to access the mailserver - standard
+     * getter
+     *
+     * @return True if authentication is used to access mailserver
+     */
+    public boolean isUseAuthentication() {
+        return useAuthentication;
+    }
+
+    /**
+     * Sets if authentication should be used to access the mailserver - to be
+     * called by SmtpSampler-object
+     *
+     * @param useAuthentication
+     *            Should authentication be used to access mailserver?
+     */
+    public void setUseAuthentication(boolean useAuthentication) {
+        this.useAuthentication = useAuthentication;
+    }
+
+    /**
+     * Returns if SSL is used to send message - standard getter
+     *
+     * @return True if SSL is used to transmit message
+     */
+    public boolean getUseSSL() {
+        return useSSL;
+    }
+
+    /**
+     * Sets SSL to secure the delivery channel for the message - to be called by
+     * SmtpSampler-object
+     *
+     * @param useSSL
+     *            Should StartTLS be used to secure SMTP-connection?
+     */
+    public void setUseSSL(boolean useSSL) {
+        this.useSSL = useSSL;
+    }
+
+    /**
+     * Returns if StartTLS is used to transmit message - standard getter
+     *
+     * @return True if StartTLS is used to transmit message
+     */
+    public boolean getUseStartTLS() {
+        return useStartTLS;
+    }
+
+    /**
+     * Sets StartTLS to secure the delivery channel for the message - to be
+     * called by SmtpSampler-object
+     *
+     * @param useStartTLS
+     *            Should StartTLS be used to secure SMTP-connection?
+     */
+    public void setUseStartTLS(boolean useStartTLS) {
+        this.useStartTLS = useStartTLS;
+    }
+
+    /**
+     * Returns port to be used for SMTP-connection (standard 25 or 465) -
+     * standard getter
+     *
+     * @return Port to be used for SMTP-connection
+     */
+    public String getSmtpPort() {
+        return smtpPort;
+    }
+
+    /**
+     * Sets port to be used for SMTP-connection (standard 25 or 465) - to be
+     * called by SmtpSampler-object
+     *
+     * @param smtpPort
+     *            Port to be used for SMTP-connection
+     */
+    public void setSmtpPort(String smtpPort) {
+        this.smtpPort = smtpPort;
+    }
+
+    /**
+     * Returns if sampler should trust all certificates - standard getter
+     *
+     * @return True if all Certificates are trusted
+     */
+    public boolean isTrustAllCerts() {
+        return trustAllCerts;
+    }
+
+    /**
+     * Determines if SMTP-sampler should trust all certificates, no matter what
+     * CA - to be called by SmtpSampler-object
+     *
+     * @param trustAllCerts
+     *            Should all certificates be trusted?
+     */
+    public void setTrustAllCerts(boolean trustAllCerts) {
+        if (useSSL) {
+            if (trustAllCerts) {
+                Security.setProperty("ssl.SocketFactory.provider",
+                        TRUST_ALL_SOCKET_FACTORY);
+            } else {
+                Security.setProperty("ssl.SocketFactory.provider", "");
+            }
+        }
+        this.trustAllCerts = trustAllCerts;
+    }
+
+    /**
+     * Instructs object to enforce StartTLS and not to fallback to plain
+     * SMTP-connection - to be called by SmtpSampler-object
+     *
+     * @param enforceStartTLS
+     *            Should StartTLS be enforced?
+     */
+    public void setEnforceStartTLS(boolean enforceStartTLS) {
+        this.enforceStartTLS = enforceStartTLS;
+    }
+
+    /**
+     * Returns if StartTLS is enforced to secure the connection, i.e. no
+     * fallback is used (plain SMTP) - standard getter
+     *
+     * @return True if StartTLS is enforced
+     */
+    public boolean isEnforceStartTLS() {
+        return enforceStartTLS;
+    }
+
+    /**
+     * Returns headers for current message - standard getter
+     *
+     * @return HashMap of headers for current message
+     */
+    public HashMap<String, String> getHeaders() {
+        return headers;
+    }
+
+    /**
+     * Sets headers for current message
+     *
+     * @param headers
+     *            HashMap of headers for current message
+     */
+    public void setHeaders(HashMap<String, String> headers) {
+        this.headers = headers;
+    }
+
+    /**
+     * Adds a header-part to current HashMap of headers - to be called by
+     * SmtpSampler-object
+     *
+     * @param headerName
+     *            Key for current header
+     * @param headerValue
+     *            Value for current header
+     */
+    public void addHeader(String headerName, String headerValue) {
+        if (this.headers == null)
+            this.headers = new HashMap<String, String>();
+        this.headers.put(headerName, headerValue);
+    }
+
+    /**
+     * Deletes all current headers in HashMap
+     */
+    public void clearHeaders() {
+        if (this.headers == null)
+            this.headers = new HashMap<String, String>();
+        else
+            this.headers.clear();
+    }
+
+    /**
+     * Returns all attachment for current message - standard getter
+     *
+     * @return List of attachments for current message
+     */
+    public List<File> getAttachments() {
+        return attachments;
+    }
+
+    /**
+     * Adds attachments to current message
+     *
+     * @param attachments
+     *            List of files to be added as attachments to current message
+     */
+    public void setAttachments(List<File> attachments) {
+        this.attachments = attachments;
+    }
+
+    /**
+     * Adds an attachment to current message - to be called by
+     * SmtpSampler-object
+     *
+     * @param attachment
+     *            File-object to be added as attachment to current message
+     */
+    public void addAttachment(File attachment) {
+        this.attachments.add(attachment);
+    }
+
+    /**
+     * Clear all attachments for current message
+     */
+    public void clearAttachments() {
+        this.attachments.clear();
+    }
+
+    /**
+     * Returns if synchronous-mode is used for current message (i.e. time for
+     * delivery, ... is measured) - standard getter
+     *
+     * @return True if synchronous-mode is used
+     */
+    public boolean isSynchronousMode() {
+        return synchronousMode;
+    }
+
+    /**
+     * Sets the use of synchronous-mode (i.e. time for delivery, ... is
+     * measured) - to be called by SmtpSampler-object
+     *
+     * @param synchronousMode
+     *            Should synchronous-mode be used?
+     */
+    public void setSynchronousMode(boolean synchronousMode) {
+        this.synchronousMode = synchronousMode;
+    }
+
+    /**
+     * Returns which protocol should be used to transport message (smtps for
+     * SSL-secured connections or smtp for plain SMTP / StartTLS)
+     *
+     * @return Protocol that is used to transport message
+     */
+    private String getProtocol() {
+        return (useSSL) ? "smtps" : "smtp";
+    }
+
+    /**
+     * Assigns the object to use a local truststore for SSL / StartTLS - to be
+     * called by SmtpSampler-object
+     *
+     * @param useLocalTrustStore
+     *            Should a local truststore be used?
+     */
+    public void setUseLocalTrustStore(boolean useLocalTrustStore) {
+        this.useLocalTrustStore = useLocalTrustStore;
+    }
+
+    /**
+     * Sets the path to the local truststore to be used for SSL / StartTLS - to
+     * be called by SmtpSampler-object
+     *
+     * @param trustStoreToUse
+     *            Path to local truststore
+     */
+    public void setTrustStoreToUse(String trustStoreToUse) {
+        this.trustStoreToUse = trustStoreToUse;
+    }
+
+    public void setUseEmlMessage(boolean sendEmlMessage) {
+        this.sendEmlMessage = sendEmlMessage;
+    }
+
+    /**
+     * Sets eml-message to be sent
+     *
+     * @param emlMessage
+     *            path to eml-message
+     */
+    public void setEmlMessage(String emlMessage) {
+        this.emlMessage = emlMessage;
+    }
+
+    public StringBuffer getServerResponse() {
+        return this.serverResponse;
+    }
+}
\ No newline at end of file

Propchange: jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/SendMailCommand.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/SendMailCommand.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/SynchronousTransportListener.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/SynchronousTransportListener.java?rev=959681&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/SynchronousTransportListener.java (added)
+++ jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/SynchronousTransportListener.java Thu Jul  1 14:34:35 2010
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jmeter.protocol.smtp.sampler.protocol;
+
+import javax.mail.event.TransportAdapter;
+import javax.mail.event.TransportEvent;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.log.Logger; // this comes out of logkit.jar and not
+
+// commons-logger
+
+/**
+ * This class implements a listener for SMTP events and a monitor for all
+ * threads sending mail. The main purpose is to synchronize the send action with
+ * the end of communication with remote smtp server, so that sending time can be
+ * measured.
+ */
+public class SynchronousTransportListener extends TransportAdapter {
+
+    private static final Logger logger = LoggingManager.getLoggerForClass();
+
+    private boolean finished = false;
+
+    /**
+     * Creates a new instance of SynchronousTransportListener
+     */
+    public SynchronousTransportListener() {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void messageDelivered(TransportEvent e) {
+        logger.debug("Message delivered");
+        finish();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void messageNotDelivered(TransportEvent e) {
+        logger.debug("Message not delivered");
+        finish();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void messagePartiallyDelivered(TransportEvent e) {
+        logger.debug("Message partially delivered");
+        finish();
+    }
+
+    /**
+     * Synchronized-method
+     *
+     * @throws InterruptedException
+     */
+    public synchronized void attend() throws InterruptedException {
+        if (!finished)
+            wait();
+    }
+
+    /**
+     * Synchronized-method
+     */
+    public synchronized void finish() {
+        finished = true;
+        notify();
+    }
+
+}

Propchange: jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/SynchronousTransportListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/SynchronousTransportListener.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/TrustAllSSLSocketFactory.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/TrustAllSSLSocketFactory.java?rev=959681&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/TrustAllSSLSocketFactory.java (added)
+++ jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/TrustAllSSLSocketFactory.java Thu Jul  1 14:34:35 2010
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jmeter.protocol.smtp.sampler.protocol;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * This class can be used as a SocketFactory with SSL-connections.
+ * Its purpose is to ensure that all certificates - no matter from which CA -are accepted to secure the SSL-connection.
+ * It has to be kept in mind that a SocketFactory must not be used with StartTLS, because the javaMail-api assumes
+ * to use SSL when using the socketFactory.class- or socketFactory.fallback-property.
+ *
+ */
+public class TrustAllSSLSocketFactory extends SSLSocketFactory  {
+
+    private final SSLSocketFactory factory;
+
+    /**
+     * Standard constructor
+     */
+    public TrustAllSSLSocketFactory(){
+        SSLContext sslcontext = null;
+        try {
+            sslcontext = SSLContext.getInstance( "TLS");
+            sslcontext.init( null, new TrustManager[]{
+                    new X509TrustManager() {
+                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+                            return null;
+                        }
+                        public void checkClientTrusted(
+                                java.security.cert.X509Certificate[] certs, String authType) {
+                        }
+                        public void checkServerTrusted(
+                                java.security.cert.X509Certificate[] certs, String authType) {
+                        }
+                    }
+                },
+                        new java.security.SecureRandom());
+        } catch (Exception e) {
+            throw new RuntimeException("Could not create the SSL context",e);
+        }
+        factory = sslcontext.getSocketFactory();
+    }
+
+    /**
+     * Factory method
+     * @return New TrustAllSSLSocketFactory
+     */
+    public static SocketFactory getDefault() {
+        return new TrustAllSSLSocketFactory();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Socket createSocket( Socket socket, String s, int i, boolean
+            flag)
+            throws IOException {
+        return factory.createSocket( socket, s, i, flag);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Socket createSocket( InetAddress inaddr, int i,
+            InetAddress inaddr1, int j) throws IOException {
+        return factory.createSocket( inaddr, i, inaddr1, j);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Socket createSocket( InetAddress inaddr, int i) throws
+            IOException {
+        return factory.createSocket( inaddr, i);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Socket createSocket( String s, int i, InetAddress inaddr, int j)
+    throws IOException {
+        return factory.createSocket( s, i, inaddr, j);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Socket createSocket( String s, int i) throws IOException {
+        return factory.createSocket( s, i);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Socket createSocket() throws IOException {
+        return factory.createSocket();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String[] getDefaultCipherSuites() {
+        return factory.getSupportedCipherSuites();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String[] getSupportedCipherSuites() {
+        return factory.getSupportedCipherSuites();
+    }
+}
\ No newline at end of file

Propchange: jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/TrustAllSSLSocketFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/protocol/TrustAllSSLSocketFactory.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/tools/CounterOutputStream.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/tools/CounterOutputStream.java?rev=959681&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/tools/CounterOutputStream.java (added)
+++ jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/tools/CounterOutputStream.java Thu Jul  1 14:34:35 2010
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jmeter.protocol.smtp.sampler.tools;
+
+import java.io.OutputStream;
+
+/**
+ * Utility-class to calculate message size.
+ */
+public class CounterOutputStream extends OutputStream {
+    int count = 0;
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+
+    public void close() {}
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void flush() {}
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void write(byte[] b, int off, int len) {
+        count += len;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void write(int b) {
+        count++;
+    }
+
+    /**
+     * Returns message size
+     * @return Message size
+     */
+    public int getCount() {
+        return count;
+    }
+}

Propchange: jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/tools/CounterOutputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/tools/CounterOutputStream.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: jakarta/jmeter/trunk/xdocs/images/screenshots/smtp_sampler.png
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/images/screenshots/smtp_sampler.png?rev=959681&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jakarta/jmeter/trunk/xdocs/images/screenshots/smtp_sampler.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Modified: jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=959681&r1=959680&r2=959681&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml Thu Jul  1 14:34:35 2010
@@ -1484,7 +1484,54 @@ In non-GUI mode, JMeter will exit if som
   <property name="Action" required="Yes">Pause / Stop / Stop Now</property>
   <property name="Duration" required="Yes, if Pause is selected">How long to pause for (milliseconds)</property>
 </properties>
-</component><a href="#">^</a>
+</component>
+
+
+<component name="SMTP Sampler"  index="&sect-num;.1.19"  width="644" height="801" screenshot="smtp_sampler.png">
+<note>
+BETA code. This sampler currently uses System properties to control some aspects of its behaviour.
+There are likely to be problems when using more than one thread with multiple samplers that have different settings;
+and the sampler may interfere with other samplers that use SSL.
+</note>
+<description>
+<p>
+The SMTP Sampler can send mail messages using SMTP/SMTPS protocol. 
+It is possible to set security propocols for the connection (SSL and TLS), as well as user authentication. 
+If a security protocol is used a verification on the server certificate will occur. <br></br>
+Two alternatives to handle this verification are available:<br></br>
+<ul>
+<li>Trust all certificates. This will ignore certificate chain verification</li>
+<li>Use a local truststore. With this option the certificate chain will be validated against the local truststore file.</li>
+</ul>
+</p>
+</description>
+<properties>
+<property name="Server" required="Yes">Hostname or IP address of the server. See below for use with <code>file</code> protocol.</property>
+<property name="Port" required="Yes">Port to be used to connect to the server (optional)</property>
+<property name="Address From" required="Yes">The from address that will appear in the e-mail</property>
+<property name="Address To" required="Yes">The destination e-mail address</property>
+<property name="Address To BCC" required="No">Blind carbon copy destinations e-mail address</property>
+<property name="Address To CC" required="No">Carbon copy destinations e-mail address</property>
+<property name="Use Auth" required="">Indicates if the SMTP server requires user authentication</property>
+<property name="Username" required="">User login name</property>
+<property name="Password" required="">User login password (N.B. this is stored unencrypted in the test plan)</property>
+<property name="Use no security features" required="">Indicates that the connection to the SMTP server does not use any security protocol.</property>
+<property name="Use SSL" required="">Indicates that the connection to the SMTP server must use the SSL protocol.</property>
+<property name="Use StartTLS" required="">Indicates that the connection to the SMTP server should attempt to start the TLS protocol.</property>
+<property name="Enforce StartTLS" required="">If the server does not start the TLS protocol the connection will be terminated.</property>
+<property name="Trust All Certificates" required="">When selected it will accept all certificates independent of the CA.</property>
+<property name="Use local truststore" required="">When selected it will only accept certificates that are locally trusted.</property>
+<property name="Local truststore" required="">Local file containing the trusted certificates.</property>
+<property name="Subject" required="">The e-mail message subject.</property>
+<property name="Include timestamp in subject" required="">Includes the System.currentTimemilis() in the subject line.</property>
+<property name="Message" required="">The message body.</property>
+<property name="Attach files" required="">Files to be attached to the message.</property>
+<property name="Send .eml" required="">If set, the .eml file will be sent instead of the entries in the Subject, Message, and Attached files</property>
+<property name="Calculate message size" required="">Calculates the message size and stores it in the sample result.</property>
+</properties>
+</component>
+
+<a href="#">^</a>
 
 </section>
 
@@ -3669,20 +3716,25 @@ The assertion comparisons can be seen in
 </properties>
 </component>
 
-<component name="SMIME Assertion" index="&sect-num;.5.13"  width="473" height="370" screenshot="assertion/smime.png">
+<component name="SMIME Assertion" index="&sect-num;.5.13"  width="471" height="428" screenshot="assertion/smime.png">
 <description>
 The SMIME Assertion can be used to evaluate the sample results from the Mail Reader Sampler.
 This assertion verifies if the body of a mime message is signed or not. The signature can also be verified against a specific signer certificate.
 As this is a functionality that is not necessarily needed by most users, additional jars need to be downloaded and added to JMETER_HOME/lib :<br></br> 
 <ul>
-<li>bcmail-jdk15-145.jar</li>
-<li>bcprov-jdk15-145.jar</li>
+<li>bcmail-xxx.jar (BouncyCastle SMIME/CMS)</li>
+<li>bcprov-xxx.jar (BouncyCastle Provider)</li>
 </ul>
+These need to be <a href="http://www.bouncycastle.org/latest_releases.html">downloaded from BouncyCastle.</a>
+<p>
+If using the <complink name="Mail Reader Sampler">Mail Reader Sampler</complink>, 
+please ensure that you select "Store the message using MIME (raw)" otherwise the Assertion won't be able to process the message correctly.
+</p>
 </description>
 <properties>
     <property name="Name" required="No">Descriptive name for this element that is shown in the tree.</property>
-    <property name="Message not signed" required="Yes">Whether or not to expect a signature in the message</property>
     <property name="Verify Signature" required="Yes">If selected, the asertion will verify if it is a valid signature according to the parameters defined in the Signer Certificate box.</property>
+    <property name="Message not signed" required="Yes">Whether or not to expect a signature in the message</property>
     <property name="Signer Cerificate" required="Yes">"No Check" means that it wil not perform signature verification. "Check values" is used to verify the signature against the inputs provided. And "Certificate file" will perform the verification against a specific certificate file.</property>
     <property name="Message Position" required="Yes">
     The Mail sampler can retrieve multiple messages in a single sample.



---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@jakarta.apache.org
For additional commands, e-mail: notifications-help@jakarta.apache.org