You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by pm...@apache.org on 2017/01/30 18:47:11 UTC

svn commit: r1780966 - in /jmeter/trunk: src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/SmtpSampler.java xdocs/changes.xml

Author: pmouawad
Date: Mon Jan 30 18:47:11 2017
New Revision: 1780966

URL: http://svn.apache.org/viewvc?rev=1780966&view=rev
Log:
Refactored and reformatted SmtpSampler
Contributed by Graham Russell
Dropped a lot of tests on message exceptions that are very fragile and only work in English locale
This closes #259

Modified:
    jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/SmtpSampler.java
    jmeter/trunk/xdocs/changes.xml

Modified: jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/SmtpSampler.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/SmtpSampler.java?rev=1780966&r1=1780965&r2=1780966&view=diff
==============================================================================
--- jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/SmtpSampler.java (original)
+++ jmeter/trunk/src/protocol/mail/org/apache/jmeter/protocol/smtp/sampler/SmtpSampler.java Mon Jan 30 18:47:11 2017
@@ -23,11 +23,11 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import javax.mail.AuthenticationFailedException;
 import javax.mail.BodyPart;
@@ -40,6 +40,7 @@ import javax.mail.internet.AddressExcept
 import javax.mail.internet.ContentType;
 import javax.mail.internet.InternetAddress;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.jmeter.config.ConfigTestElement;
 import org.apache.jmeter.protocol.smtp.sampler.gui.SecuritySettingsPanel;
 import org.apache.jmeter.protocol.smtp.sampler.protocol.SendMailCommand;
@@ -71,8 +72,6 @@ public class SmtpSampler extends Abstrac
 
     //+JMX file attribute names - do not change any values!
     public static final String SERVER               = "SMTPSampler.server"; // $NON-NLS-1$
-
-
     public static final String SERVER_PORT          = "SMTPSampler.serverPort"; // $NON-NLS-1$
     public static final String SERVER_TIMEOUT       = "SMTPSampler.serverTimeout"; // $NON-NLS-1$
     public static final String SERVER_CONNECTION_TIMEOUT = "SMTPSampler.serverConnectionTimeout"; // $NON-NLS-1$
@@ -109,194 +108,182 @@ public class SmtpSampler extends Abstrac
     /**
      * Performs the sample, and returns the result
      *
-     * @param e
-     *            Standard-method-header from JMeter
-     * @return sampleresult Result of the sample
+     * @param e Standard-method-header from JMeter
+     * @return Result of the sample
      * @see org.apache.jmeter.samplers.Sampler#sample(org.apache.jmeter.samplers.Entry)
      */
     @Override
     public SampleResult sample(Entry e) {
-        Message message = null;
-        SampleResult res = new SampleResult();
-        res.setSampleLabel(getName());
-        boolean isOK = false; // Did sample succeed?
-        SendMailCommand instance = new SendMailCommand();
-        instance.setSmtpServer(getPropertyAsString(SmtpSampler.SERVER));
-        instance.setSmtpPort(getPropertyAsString(SmtpSampler.SERVER_PORT));
-        instance.setConnectionTimeOut(getPropertyAsString(SmtpSampler.SERVER_CONNECTION_TIMEOUT));
-        instance.setTimeOut(getPropertyAsString(SmtpSampler.SERVER_TIMEOUT));
-
-        instance.setUseSSL(getPropertyAsBoolean(SecuritySettingsPanel.USE_SSL));
-        instance.setUseStartTLS(getPropertyAsBoolean(SecuritySettingsPanel.USE_STARTTLS));
-        instance.setTrustAllCerts(getPropertyAsBoolean(SecuritySettingsPanel.SSL_TRUST_ALL_CERTS));
-        instance.setEnforceStartTLS(getPropertyAsBoolean(SecuritySettingsPanel.ENFORCE_STARTTLS));
-
-        instance.setUseAuthentication(getPropertyAsBoolean(USE_AUTH));
-        instance.setUsername(getPropertyAsString(USERNAME));
-        instance.setPassword(getPropertyAsString(PASSWORD));
-
-        instance.setUseLocalTrustStore(getPropertyAsBoolean(SecuritySettingsPanel.USE_LOCAL_TRUSTSTORE));
-        instance.setTrustStoreToUse(getPropertyAsString(SecuritySettingsPanel.TRUSTSTORE_TO_USE));
-        instance.setEmlMessage(getPropertyAsString(EML_MESSAGE_TO_SEND));
-        instance.setUseEmlMessage(getPropertyAsBoolean(USE_EML));
+        SendMailCommand sendMailCmd;
+        Message message;
+        SampleResult result = createSampleResult();
 
-        instance.setEnableDebug(getPropertyAsBoolean(ENABLE_DEBUG));
-
-        if (getPropertyAsString(MAIL_FROM).matches(".*@.*")) {
-            instance.setSender(getPropertyAsString(MAIL_FROM));
+        try {
+            sendMailCmd = createSendMailCommandFromProperties();
+            message = sendMailCmd.prepareMessage();
+            result.setBytes(calculateMessageSize(message));
+        } catch (Exception ex) {
+            log.warn("Error while preparing message", ex);
+            result.setResponseCode("500");
+            result.setResponseMessage(ex.toString());
+            return result;
         }
 
-        final String receiverTo = getPropertyAsString(SmtpSampler.RECEIVER_TO).trim();
-        final String receiverCC = getPropertyAsString(SmtpSampler.RECEIVER_CC).trim();
-        final String receiverBcc = getPropertyAsString(SmtpSampler.RECEIVER_BCC).trim();
-        final String replyTo = getPropertyAsString(SmtpSampler.MAIL_REPLYTO).trim();
-
+        // Set up the sample result details
+        result.setDataType(SampleResult.TEXT);
         try {
-            // Process address lists
-            instance.setReceiverTo(getPropNameAsAddresses(receiverTo));
-            instance.setReceiverCC(getPropNameAsAddresses(receiverCC));
-            instance.setReceiverBCC(getPropNameAsAddresses(receiverBcc));
-            instance.setReplyTo(getPropNameAsAddresses(replyTo));
-
-            if(getPropertyAsBoolean(SUPPRESS_SUBJECT)){
-                instance.setSubject(null);
-            }else{
-                String subject = getPropertyAsString(SUBJECT);
-                if (getPropertyAsBoolean(INCLUDE_TIMESTAMP)){
-                    StringBuilder sb = new StringBuilder(subject);
-                    sb.append(" <<< current timestamp: ");
-                    sb.append(new Date().getTime());
-                    sb.append(" >>>");
-                    subject = sb.toString();
-                }
-                instance.setSubject(subject);
-            }
+            result.setRequestHeaders(getRequestHeaders(message));
+            result.setSamplerData(getSamplerData(message));
+        } catch (MessagingException | IOException ex) {
+            result.setSamplerData("Error occurred trying to save request info: " + ex);
+            log.warn("Error occurred trying to save request info", ex);
+        }
 
-            if (!getPropertyAsBoolean(USE_EML)) { // part is only needed if we
-                // don't send an .eml-file
-                instance.setMailBody(getPropertyAsString(MESSAGE));
-                instance.setPlainBody(getPropertyAsBoolean(PLAIN_BODY));
-                final String filesToAttach = getPropertyAsString(ATTACH_FILE);
-                if (!filesToAttach.isEmpty()) {
-                    String[] attachments = filesToAttach.split(FILENAME_SEPARATOR);
-                    for (String attachment : attachments) {
-                        File file = new File(attachment);
-                        if(!file.isAbsolute() && !file.exists()){
-                            log.debug("loading file with relative path: " +attachment);
-                            file = new File(FileServer.getFileServer().getBaseDir(), attachment);
-                            log.debug("file path set to: "+attachment);
-                        }
-                        instance.addAttachment(file);
-                    }
-                }
+        // Perform the sampling
+        result.sampleStart();
+        boolean isSuccessful = executeMessage(result, sendMailCmd, message);
+        result.sampleEnd();
 
-            }
+        try {
+            result.setResponseData(processSampler(message));
+        } catch (IOException | MessagingException ex) {
+            log.warn("Failed to set result response data", ex);
+        }
 
-            // needed for measuring sending time
-            instance.setSynchronousMode(true);
+        result.setSuccessful(isSuccessful);
 
-            instance.setHeaderFields((CollectionProperty)getProperty(SmtpSampler.HEADER_FIELDS));
-            message = instance.prepareMessage();
+        return result;
+    }
 
-            if (getPropertyAsBoolean(MESSAGE_SIZE_STATS)) {
-                // calculate message size
-                CounterOutputStream cs = new CounterOutputStream();
-                message.writeTo(cs);
-                res.setBytes(cs.getCount());
-            } else {
-                res.setBytes(-1L);
-            }
+    private SampleResult createSampleResult() {
+        SampleResult result = new SampleResult();
+        result.setSampleLabel(getName());
+        return result;
+    }
 
+    private boolean executeMessage(SampleResult result, SendMailCommand sendMailCmd, Message message) {
+        boolean didSampleSucceed = false;
+        try {
+            sendMailCmd.execute(message);
+            result.setResponseCodeOK();
+            result.setResponseMessage(
+                    "Message successfully sent!\n" + sendMailCmd.getServerResponse());
+            didSampleSucceed = true;
+        } catch (AuthenticationFailedException afex) {
+            log.warn("", afex);
+            result.setResponseCode("500");
+            result.setResponseMessage(
+                    "AuthenticationFailedException: authentication failed - wrong username / password!\n"
+                            + afex);
         } catch (Exception ex) {
-            log.warn("Error while preparing message", ex);
-            res.setResponseCode("500");
-            res.setResponseMessage(ex.toString());
-            return res;
+            log.warn("", ex);
+            result.setResponseCode("500");
+            result.setResponseMessage(ex.getMessage());
         }
+        return didSampleSucceed;
+    }
 
-        // Set up the sample result details
-        res.setDataType(SampleResult.TEXT);
-        try {
-            res.setRequestHeaders(getRequestHeaders(message));
-            res.setSamplerData(getSamplerData(message));
-        } catch (MessagingException | IOException e1) {
-            res.setSamplerData("Error occurred trying to save request info: "+e1);
-            log.warn("Error occurred trying to save request info",e1);
+    private long calculateMessageSize(Message message) throws IOException, MessagingException {
+        if (getPropertyAsBoolean(MESSAGE_SIZE_STATS)) {
+            // calculate message size
+            CounterOutputStream cs = new CounterOutputStream();
+            message.writeTo(cs);
+            return cs.getCount();
+        } else {
+            return -1L;
         }
+    }
 
-        // Perform the sampling
-        res.sampleStart();
+    private byte[] processSampler(Message message) throws IOException, MessagingException {
+        // process the sampler result
+        try (InputStream is = message.getInputStream()) {
+            return IOUtils.toByteArray(is);
+        }        
+    }
 
-        try {
-            instance.execute(message);
+    private List<File> getAttachmentFiles() {
+        final String[] attachments = getPropertyAsString(ATTACH_FILE).split(FILENAME_SEPARATOR);
+        return Arrays.stream(attachments)
+                .map(this::attachmentToFile)
+                .collect(Collectors.toList());
+    }
 
-            res.setResponseCodeOK();
-            /*
-             * TODO if(instance.getSMTPStatusCode == 250)
-             * res.setResponseMessage("Message successfully sent!"); else
-             * res.setResponseMessage(instance.getSMTPStatusCodeIncludingMessage);
-             */
-            res.setResponseMessage("Message successfully sent!\n"
-                    + instance.getServerResponse());
-            isOK = true;
-        }
-        // username / password incorrect
-        catch (AuthenticationFailedException afex) {
-            log.warn("", afex);
-            res.setResponseCode("500");
-            res.setResponseMessage("AuthenticationFailedException: authentication failed - wrong username / password!\n"
-                            + afex);
-        // SSL not supported, startTLS not supported, other messagingException
-        } catch (MessagingException mex) {
-            log.warn("",mex);
-            res.setResponseCode("500");
-            if (mex.getMessage().matches(".*Could not connect to SMTP host.*465.*")
-                    && mex.getCause().getMessage().matches(".*Connection timed out.*")) {
-                res.setResponseMessage("MessagingException: Probably, SSL is not supported by the SMTP-Server!\n"
-                                + mex);
-            } else if (mex.getMessage().matches(".*StartTLS failed.*")) {
-                res.setResponseMessage("MessagingException: StartTLS not supported by server or initializing failed!\n"
-                                + mex);
-            } else if (mex.getMessage().matches(".*send command to.*")
-                    && mex.getCause().getMessage().matches(
-                                    ".*unable to find valid certification path to requested target.*")) {
-                res.setResponseMessage("MessagingException: Server certificate not trusted - perhaps you have to restart JMeter!\n"
-                                + mex);
-            } else {
-                res.setResponseMessage("Other MessagingException: " + mex.toString());
+    private File attachmentToFile(String attachment) {
+        File file = new File(attachment);
+        if (!file.isAbsolute() && !file.exists()) {
+            if(log.isDebugEnabled()) {
+                log.debug("loading file with relative path: " + attachment);
             }
-        }  catch (Exception ex) {   // general exception
-            log.warn("",ex);
-            res.setResponseCode("500");
-            if (null != ex.getMessage()
-                    && ex.getMessage().matches("Failed to build truststore")) {
-                res.setResponseMessage("Failed to build truststore - did not try to send mail!");
-            } else {
-                res.setResponseMessage("Other Exception: " + ex.toString());
+            file = new File(FileServer.getFileServer().getBaseDir(), attachment);
+            if(log.isDebugEnabled()) {
+                log.debug("file path set to: " + attachment);
             }
         }
+        return file;
+    }
 
-        res.sampleEnd();
-
-        try {
-            // process the sampler result
-            InputStream is = message.getInputStream();
-            StringBuilder sb = new StringBuilder();
-            byte[] buf = new byte[1024];
-            int read = is.read(buf);
-            while (read > 0) {
-                sb.append(new String(buf, 0, read));  // TODO - charset?
-                read = is.read(buf);
+    private String calculateSubject() {
+        if (getPropertyAsBoolean(SUPPRESS_SUBJECT)) {
+            return null;
+        } else {
+            String subject = getPropertyAsString(SUBJECT);
+            if (getPropertyAsBoolean(INCLUDE_TIMESTAMP)) {
+                subject = subject
+                        + " <<< current timestamp: "
+                        + System.currentTimeMillis()
+                        + " >>>";
             }
-            // TODO - charset?
-            res.setResponseData(sb.toString().getBytes()); // TODO this should really be request data, but there is none
-        } catch (IOException | MessagingException ex) {
-            log.warn("",ex);
+            return subject;
+        }
+    }
+
+    private SendMailCommand createSendMailCommandFromProperties() throws AddressException {
+        SendMailCommand sendMailCmd = new SendMailCommand();
+        sendMailCmd.setSmtpServer(getPropertyAsString(SmtpSampler.SERVER));
+        sendMailCmd.setSmtpPort(getPropertyAsString(SmtpSampler.SERVER_PORT));
+        sendMailCmd.setConnectionTimeOut(getPropertyAsString(SmtpSampler.SERVER_CONNECTION_TIMEOUT));
+        sendMailCmd.setTimeOut(getPropertyAsString(SmtpSampler.SERVER_TIMEOUT));
+
+        sendMailCmd.setUseSSL(getPropertyAsBoolean(SecuritySettingsPanel.USE_SSL));
+        sendMailCmd.setUseStartTLS(getPropertyAsBoolean(SecuritySettingsPanel.USE_STARTTLS));
+        sendMailCmd.setTrustAllCerts(getPropertyAsBoolean(SecuritySettingsPanel.SSL_TRUST_ALL_CERTS));
+        sendMailCmd.setEnforceStartTLS(getPropertyAsBoolean(SecuritySettingsPanel.ENFORCE_STARTTLS));
+
+        sendMailCmd.setUseAuthentication(getPropertyAsBoolean(USE_AUTH));
+        sendMailCmd.setUsername(getPropertyAsString(USERNAME));
+        sendMailCmd.setPassword(getPropertyAsString(PASSWORD));
+
+        sendMailCmd.setUseLocalTrustStore(getPropertyAsBoolean(SecuritySettingsPanel.USE_LOCAL_TRUSTSTORE));
+        sendMailCmd.setTrustStoreToUse(getPropertyAsString(SecuritySettingsPanel.TRUSTSTORE_TO_USE));
+
+        sendMailCmd.setEmlMessage(getPropertyAsString(EML_MESSAGE_TO_SEND));
+        sendMailCmd.setUseEmlMessage(getPropertyAsBoolean(USE_EML));
+        if (!getPropertyAsBoolean(USE_EML)) {
+            // if we are not sending an .eml file
+            sendMailCmd.setMailBody(getPropertyAsString(MESSAGE));
+            sendMailCmd.setPlainBody(getPropertyAsBoolean(PLAIN_BODY));
+            getAttachmentFiles().forEach(sendMailCmd::addAttachment);
+        }
+
+        sendMailCmd.setEnableDebug(getPropertyAsBoolean(ENABLE_DEBUG));
+
+        if (getPropertyAsString(MAIL_FROM).matches(".*@.*")) {
+            sendMailCmd.setSender(getPropertyAsString(MAIL_FROM));
         }
 
-        res.setSuccessful(isOK);
+        // Process address lists
+        sendMailCmd.setReceiverTo(getPropAsAddresses(SmtpSampler.RECEIVER_TO));
+        sendMailCmd.setReceiverCC(getPropAsAddresses(SmtpSampler.RECEIVER_CC));
+        sendMailCmd.setReceiverBCC(getPropAsAddresses(SmtpSampler.RECEIVER_BCC));
+        sendMailCmd.setReplyTo(getPropAsAddresses(SmtpSampler.MAIL_REPLYTO));
+        sendMailCmd.setSubject(calculateSubject());
 
-        return res;
+        // needed for measuring sending time
+        sendMailCmd.setSynchronousMode(true);
+
+        sendMailCmd.setHeaderFields((CollectionProperty) getProperty(SmtpSampler.HEADER_FIELDS));
+
+        return sendMailCmd;
     }
 
     private String getRequestHeaders(Message message) throws MessagingException {
@@ -314,7 +301,7 @@ public class SmtpSampler extends Abstrac
             Multipart multipart = (Multipart) content;
             String contentType = multipart.getContentType();
             ContentType ct = new ContentType(contentType);
-            String boundary=ct.getParameter("boundary");
+            String boundary = ct.getParameter("boundary");
             for (int i = 0; i < multipart.getCount(); i++) { // throws ME
                 sb.append("--");
                 sb.append(boundary);
@@ -326,13 +313,14 @@ public class SmtpSampler extends Abstrac
             sb.append(boundary);
             sb.append("--");
             sb.append("\n");
-        } else if(content instanceof BodyPart){
+        } else if (content instanceof BodyPart) {
             BodyPart bodyPart = (BodyPart) content;
             writeBodyPart(sb, bodyPart); // throws IOE, ME
-        } else if (content instanceof String){
+        } else if (content instanceof String) {
             sb.append(content);
         } else {
-            sb.append("Content has class: "+content.getClass().getCanonicalName());
+            sb.append("Content has class: ");
+            sb.append(content.getClass().getCanonicalName());
         }
         return sb.toString();
     }
@@ -365,14 +353,16 @@ public class SmtpSampler extends Abstrac
     /**
      * Get the list of addresses or null.
      * Null is treated differently from an empty list.
-     * @param propValue addresses separated by ";"
+     *
+     * @param propKey key of the property containing addresses separated by ";"
      * @return the list or null if the input was the empty string
-     * @throws AddressException
+     * @throws AddressException thrown if any address is an illegal format
      */
-    private List<InternetAddress> getPropNameAsAddresses(String propValue) throws AddressException{
-        if (propValue.length() > 0){ // we have at least one potential address
+    private List<InternetAddress> getPropAsAddresses(String propKey) throws AddressException {
+        final String propValue = getPropertyAsString(propKey).trim();
+        if (!propValue.isEmpty()) { // we have at least one potential address
             List<InternetAddress> addresses = new ArrayList<>();
-            for (String address : propValue.split(";")){
+            for (String address : propValue.split(";")) {
                 addresses.add(new InternetAddress(address.trim()));
             }
             return addresses;
@@ -380,7 +370,6 @@ public class SmtpSampler extends Abstrac
             return null;
         }
     }
-    
 
     /**
      * @see org.apache.jmeter.samplers.AbstractSampler#applies(org.apache.jmeter.config.ConfigTestElement)

Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1780966&r1=1780965&r2=1780966&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml [utf-8] (original)
+++ jmeter/trunk/xdocs/changes.xml [utf-8] Mon Jan 30 18:47:11 2017
@@ -117,6 +117,7 @@ JMeter now requires Java 8. Ensure you u
 <h3>Other samplers</h3>
 <ul>
     <li><bug>60585</bug>JMS Publisher and JMS Subscriber : Allow reconnection on error and pause between errors. Based on <pr>240</pr> from by Logan Mauzaize (logan.mauzaize at gmail.com) and Maxime Chassagneux (maxime.chassagneux at gmail.com).</li>
+    <li><pr>259</pr>Refactored and reformatted SmtpSampler. Contributed by Graham Russell (graham at ham1.co.uk)</li>
 </ul>
 
 <h3>Controllers</h3>