Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    How best to deal with slow SMTP?

    I started to transition from a local SMTP Relay (Windows SMTP service enabled on the same box where web server is running) to an external one.

    I'm using an OperationBinding with mail elements.
    Code:
            <operationBinding 
                appScreen="submit"
                operationType="fetch"
                operationId="sendEmailsOnSubmitRequest"
            >
                <selectClause>PK</selectClause>
                <tableClause>${defaultTableClause}</tableClause>
                <whereClause>PK=${criteria.PK}</whereClause>
    
                <!-- Send E-mail: From Requestor to Approver -->
                <mail contentType="text/html">
                    <from>${criteria.NOREPLY}</from>
                    <to>${criteria.APPROVER}</to>
                    <subject>${criteria.SUBJECT}</subject>
                    <messageTemplate>${criteria.MESSAGE2APPROVER}</messageTemplate>
                </mail>
    
                <!-- Send E-mail: From Requestor To Requestor (Receipt-to-Self) -->
                <mail contentType="text/html">
                    <from>${criteria.NOREPLY}</from>
                    <to>${criteria.REQUESTOR}</to>
                    <subject>${criteria.SUBJECT}</subject>
                    <messageTemplate>${criteria.MESSAGE2SELF}</messageTemplate>
                </mail>
            </operationBinding>
    The external SMTP Relay works, but it's really slow, ~8 seconds per message. The client GUI hangs until the SMTP operation is completed. "Hourglass" appears next to mouse cursor, app buttons are "disabled" (non-responsive).

    Issue #1: It appears the client is waiting for a callback response from the SMTP operation. Is there a way to not wait? Just send and forget? Recode to DMI with no return?

    Issue #2: How to turn up log level for SMTP operations? I've turned everything in log4j.isc.config.xml to "DEBUG", but all I ever see for SMTP is
    "...INFO MailMessage - trying to connect to SMTPRELAY.MYDOMAIN"

    Please advise, thanks.

    -------------------------
    SmartClient Version: v12.0p_2019-11-22/PowerEdition Deployment (built 2019-11-22)
    Chrome Version 80.0.3987.116 (Official Build) (64-bit)


    #2
    DMI alternative works as desired. Email message gets sent off, no waiting for reply.

    Client fetch calls OperationId for DMI OperationBinding to call server side Java class:
    Code:
    <operationBinding
        operationId="smtpTest"
        operationType="fetch"
    >            
        <serverObject 
            lookupStyle="new"
            className="com.smartgwt.sample.server.SmtpTest"
            methodName="doSmtpTest"
        />              
    </operationBinding>
    Server-side Java class uses method with void return to create/send email message.

    Code:
    package com.smartgwt.sample.server;
    
    import java.util.Map;
    
    import com.isomorphic.datasource.DSRequest;
    import com.isomorphic.mail.MailMessage;
    
    public class SmtpTest {
    
        Map<String, String> dtoMap = null;
    
        MailMessage message = new MailMessage();
    
        @SuppressWarnings("unchecked")
        public void doSmtpTest(DSRequest incomingDsRequest) {
    
            try {
                dtoMap = incomingDsRequest.getValues();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            message.addHeader("Content-Type", "text/html");
    
            String from = dtoMap.get("NOREPLY");
            message.setFrom(from);
    
            String to = dtoMap.get("APPROVER");
            message.setRecipient(to);
    
            String subject = dtoMap.get("SUBJECT");
            message.setSubject(subject);
    
            String message2Approver = dtoMap.get("MESSAGE2APPROVER");
            message.setBody(message2Approver);
    
            try {
                message.send();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }
    Zero perceived lag time on the client side.

    But I'll have to recode this in several places.

    If I'm missing something, please let me know.

    Feature Request: Add new attribute for Velocity emails, something like...
    Code:
    <mail 
        contentType="text/html"
        waitForCallback="false"  <<<<<<< THIS
    >
        <from>${criteria.NOREPLY}</from>
        <to>${criteria.APPROVER}</to>
        <subject>${criteria.SUBJECT}</subject>
        <messageTemplate>${criteria.MESSAGE2APPROVER}</messageTemplate>
    </mail>

    Comment


      #3
      What you're doing here is the same as the built-in XML approach and would be synchronous, blocking the request until the mail has been delivered to the mail server. If it appears faster, it's probably because your mail relay happened to be responding more quickly when you did your test. Or because you inadvertently used a different relay for that test.

      Regardless of what happened, if you want to do anything that might take a while but respond immediately to the browser, you either:
      1) spawn a new thread and do the work in that thread
      OR
      2) use Quartz or a similar scheduling system to do essentially the same thing, but with a thread pool implementation and the ability to monitor for stuck or failed tasks

      Comment


        #4
        Sterling advice, thanks!

        You are correct, I was looking at the wrong SMTP server. Testing fatigue, thankfully not as painful as that time with the electrical junction box :)

        For now, I'll take the new-thread approach.
        Code:
        Calling class...
        
        Map<String, String> message2Requestor = new HashMap<>();
        message2Requestor.put("TO", dtoMap.get("requestorEmailAddress"));
        message2Requestor.put("SUBJECT", dtoMap.get("requestorEmailSubject"));
        message2Requestor.put("MESSAGE", dtoMap.get("requestorEmailMessage"));
        
        // Send!
        Thread threadRequestor = new Thread(new RunnableMailMessage(message2Requestor));
        threadRequestor.start();
        ...
        Code:
        public class RunnableMailMessage extends MailMessage implements Runnable {
        
            private final static String noReplyEmailAddress = "No-Reply@MyDomain.com";
        
            public RunnableMailMessage(Map<String, String> dtoMap) {
        
                addHeader("Content-Type", "text/html");
        
                setFrom(noReplyEmailAddress);
        
                String to = dtoMap.get("TO");
                setRecipient(to);
        
                String subject = dtoMap.get("SUBJECT");
                setSubject(subject);
        
                String message = dtoMap.get("MESSAGE");
                setBody(message);
            }
        
            // Code in here executes per external call to thread.start()
            @Override
            public void run() {
        
                try {
        
                    send();
        
                } catch (Exception e) {
        
                    log.error("MyApp SMTP error in " + getClass().getName() + ": " + e.getMessage());
                }
            }
        }

        Comment

        Working...
        X