function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Sajiv Kartha 3Sajiv Kartha 3 

InboundEmailHandler Code works fine on Outlook 2010, but not on Outlook 2016. Always routs to exception

We have an Email Response feature.  The user receives a mail in their inbox and they can just click on Reply, type the word 'Approve' or 'Reject' and send it.

Now, this is working perfectly well on Outlook 2010 versions.  After the automatic upgrade to Outlook 2016, the Reply mails are all getting routed to exceptons.  Any clues on why this issue occurs.  We tried putting in debug statements, but are unable to specifically point the error.

This works fine on the webmail versions of Oulook 2016, but NOT on the Outlook application that is there on the desktops of the users.
Since majority of the users have migrated to the new Outlook 2016, we need to fix it.  Here is the code.

global class LeaseApproval_EmailResponseHandler implements Messaging.InboundEmailHandler {
    
    global Messaging.InboundEmailResult handleInboundEmail(Messaging.inboundEmail email,
                                                                Messaging.InboundEnvelope env) {
 
        // Create an InboundEmailResult object for returning the result of the
        // Apex Email Service
        Diagnostics.push('Approval email service');
        Messaging.InboundEmailResult result = new Messaging.InboundEmailResult();
        String myPlainText= '';
        String myHTMLText= '';
        myPlainText = email.plainTextBody;
        myHTMLText = email.htmlBody;
        Schema.DescribeSObjectResult opr = Opportunity.sObjectType.getDescribe();
        String oppPrefix = opr.getKeyPrefix();
        integer oppIdStartPos = myPlainText.indexOf(oppPrefix);
        String oppIdStr = myPlainText.subString(oppIdStartPos, oppIdStartPos+15);
        system.debug(oppIdStr);
        Id oppId = id.valueOf(oppIdStr);
        try{
            
            //we need to get the first word of text, check if it's "Approved" or "Rejected", then parse the comments before the first <hr/> tag
            integer firstSpace = myPlainText.indexOf('\n');
            String decisionStr = myPlainText.substring(0,firstSpace);
            system.debug(decisionStr);
            integer commentEnd = myPlainText.indexOf('\n\n');
            String comments = myPlainText.substring(firstSpace, commentEnd);
            

            Schema.DescribeSObjectResult ar = Lease_Approval_Role__c.sObjectType.getDescribe();
            String approvalPrefix = ar.getKeyPrefix();
            System.debug(approvalPrefix);
            integer idStartPos = myHTMLText.indexOf(approvalPrefix);
            String approvalIdStr = myHTMLText.subString(idStartPos, idStartPos+15);
            system.debug(approvalIdStr);
            Id approvalId = id.valueOf(approvalIdStr);

            //we need to find the id that should be in a hidden div in the origional email text
            Lease_Approval_Role__c existing = [Select Id, Comments__c, User__c from Lease_Approval_Role__c where ID = : approvalId];
            if(!(comments.trim()==''||comments.trim()==null)){
                existing.Comments__c = comments.trim();
            }
            String newStatus;
            if(!(decisionStr.equalsIgnoreCase('approved')||decisionStr.equalsIgnoreCase('rejected')||decisionStr.equalsIgnoreCase('reject')||decisionStr.equalsIgnoreCase('approve')||decisionStr.equalsIgnoreCase('nfw'))){
                //invalid response
                sendInvalidEmailNotification(email, oppId);
                system.debug('Bad Response' + decisionStr);
            }
            else if(decisionStr.equalsIgnoreCase('approved')||decisionStr.equalsIgnoreCase('approve')){
                newStatus = 'Approved';
            }
            else if(decisionStr.equalsIgnoreCase('rejected')||decisionStr.equalsIgnoreCase('reject')||decisionStr.equalsIgnoreCase('nfw')){
                newStatus = 'Rejected';
            }
            existing.Status__c = newStatus;
            if(newStatus=='Approved'){
                //try and get the user to set
                try{
                    system.debug('From: ' + email.fromAddress);
                    User approvedBy = [Select Id from User where Email = :email.fromAddress and isActive = true limit 1];
                    existing.Approved_By__c = approvedBy.Id;
                }
                catch(QueryException e){
                    //what are we to do?
                    existing.Approved_By__c = existing.User__c;
                    system.debug(e.getMessage() + ' ' + e.getStackTraceString());
                }
                existing.Submitted_Date__c = system.today();
            }
            else if(newStatus=='Rejected'){
                //try and get the user to set
                try{
                    system.debug('From: ' + email.fromAddress);
                    User approvedBy = [Select Id from User where Email = :email.fromAddress and isActive = true limit 1];
                    existing.Rejected_By__c = approvedBy.Id;
                }
                catch(QueryException e){
                    //what are we to do?
                    existing.Rejected_By__c = existing.User__c;
                    system.debug(e.getMessage() + ' ' + e.getStackTraceString());
                }
                existing.Submitted_Date__c = system.today();
            }
            update existing;
            result.success = true;
            return result;
        }
        catch(Exception e){
            sendInvalidEmailNotification(email, oppId);
            system.debug('Exception: ' + e.getMessage() + e.getStackTraceString());
            result.success = false;
            return result;
        }
    }

    public static void sendInvalidEmailNotification(Messaging.inboundEmail badEmail, Id opportunityId){
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();

        Opportunity relatedOpp = [Select Id, Name from Opportunity where Id = : opportunityId];
        //email.setToAddresses(new List<String>{'jimmy@redpointsolutions.com'});
        email.setToAddresses(new List<String>{badEmail.fromAddress});
        email.setReplyTo('noreply@prologis.com');
        email.setSubject('ERROR - Invalid Reply for ' + relatedOpp.Name);
        String body = 'Your email reply for <a href="'+relatedOpp.Id+'">'+relatedOpp.Name+'</a> did not send due to invalid inputs.  <b>Do not reply to this email.</b>  Please reply again to the Approval Request email using the correct format.  Please type the word Approve or Reject as the first word in the first line of your reply.  To include comments, hit “return” after your response, and type any comments starting on the second line of your reply.';
        email.setHTMLBody(body);
        system.debug('Email? '+email);
        Messaging.sendEmail(new List<Messaging.SingleEmailMessage>{email});
    }
}

 
Best Answer chosen by Sajiv Kartha 3
Sajiv Kartha 3Sajiv Kartha 3
I got the error due to which the exception mail was getting thrown.  The content we receive is a html.  A couple of fields were not getting appended in the ahref tag.  This is happening only on Outlook 2016.  Works fine on previous versions of Outlook and also on the Web version of Outlook 2016.  It is only in the Desktop App Outlook 2016, we have this issue.  

I need to know why the href content gets ignored in the inbound mail when sent from Outlook 2016.  I will raise a new question.

For now, this can be considered as 'Solved'

Thanks
Sajiv

All Answers

Sajiv Kartha 3Sajiv Kartha 3
Any updates from anyone ?

The inbound mail always routes to the exception  mail method  -   public static void sendInvalidEmailNotification(Messaging.inboundEmail badEmail, Id opportunityId){

Is there any format change that needs to be done for the inbound mail received?

Thanks
Sajiv
Sajiv Kartha 3Sajiv Kartha 3
I got the error due to which the exception mail was getting thrown.  The content we receive is a html.  A couple of fields were not getting appended in the ahref tag.  This is happening only on Outlook 2016.  Works fine on previous versions of Outlook and also on the Web version of Outlook 2016.  It is only in the Desktop App Outlook 2016, we have this issue.  

I need to know why the href content gets ignored in the inbound mail when sent from Outlook 2016.  I will raise a new question.

For now, this can be considered as 'Solved'

Thanks
Sajiv
This was selected as the best answer