0

Im trying to make a mail reminder on case object to every owner/case.. but everytime I execute the code, there`s an error

System.EmailException: SendEmail failed. First exception on row 4; first error: INVALID_EMAIL_ADDRESS, Email address is invalid: null: [toAddresses, null]

this is the code :

global class SchReminderActivitytoOwner implements Schedulable  {


    public static String CRON_EXP = '0 0 0 3 9 ? 2022';
    global void execute(SchedulableContext ctx) {

    List<Messaging.SingleEmailMessage> listmail = new List<Messaging.SingleEmailMessage>();
    EmailTemplate et = [SELECT Id, Subject, HtmlValue FROM EmailTemplate WHERE developerName = 'ET_Case_Reminder_Test22'];

    String subject = 'Testing Reminder';                            
    String htmlBody ='';


    map<string, list<case>> mapOwnerEmailtoCaseList = new map<string, list<case>>();
    map<string, user> mapEmailtoUser = new map<string, user>();
    for(Case objCase : [SELECT Id, Owner.Email, Status, Owner.Name, CaseNumber, CreatedBy.Name,Subject, OwnerId, SLA_Case_Closed_Days__c  FROM Case where Status != 'Closed']){

        if(mapOwnerEmailtoCaseList.containsKey(objCase.Owner.Email)) {
            List<Case> lstCase = mapOwnerEmailtoCaseList.get(objCase.Owner.Email);
            lstCase.add(objCase);
            mapOwnerEmailtoCaseList.put(objCase.Owner.Email, lstCase);
        } else {
            mapOwnerEmailtoCaseList.put(objCase.Owner.Email, new List<Case> { objCase });
        }
    }               

    for(User objUser : [SELECT Id, Name, ProfileId, Profile.Name, isActive,Email FROM User 
                        WHERE Email =: mapOwnerEmailtoCaseList.keyset() and IsActive = TRUE]){

        mapEmailtoUser.put(objUser.Email, objUser);
    }        

    map<string, string> mapOwnerEmailtoEmail = new map<string, string>();        
    for(string strOwnerEmail : mapOwnerEmailtoCaseList.keyset()){

        User objUser = mapEmailtoUser.get(strOwnerEmail);
        htmlBody = '<h1>***JANGAN DIBALAS/DO NOT REPLY***</h1><br>Dear {!Case.OwnerFullName}, <br>Mohon untuk menindaklanjuti pengajuan interaksi berikut ini sebelum melewati waktu SLA :<br><br><table border="1" style="border-collapse: collapse"><tr><th><b>Ticket Number</b></th><th><b>Subject</b></th><th><b>SLA Handling Time Target</b></th><th><b>Created By</b></th><th><b>Detail</b></th></tr>';
        list<Case> lstCase = mapOwnerEmailtoCaseList.get(strOwnerEmail);
        for(Case cs : lstCase){

            String TicketNumber = String.Valueof(cs.CaseNumber); if(cs.CaseNumber == null){TicketNumber = '[Not Provided]';}
            String Sbj = cs.Subject; if(cs.Subject == null){Sbj = '[Not Provided]';}
            String HandlingTimeTarget = String.Valueof(cs.SLA_Case_Closed_Days__c); if(cs.SLA_Case_Closed_Days__c == null){TicketNumber = '[Not Provided]';}
            String Link = cs.Id; if(cs.Id == null){Link = '[Not Provided]';}
            String PIC = cs.CreatedBy.Name; if(cs.CreatedBy.Name == null){PIC = '[Not Provided]';}

            htmlBody = htmlBody.replace('{!Case.OwnerFullName}', cs.Owner.Name);
            /*htmlBody = htmlBody.replace('{!Case.Ticket_Number__c}', String.Valueof(cs.CaseNumber));
            //htmlBody = htmlBody.replace('{!Case.Subject}', cs.Subject);
            //htmlBody = htmlBody.replace('{!Case.SLA_Handling_Time_Target__c}', String.Valueof(cs.SLA_Case_Closed_Days__c)); */        
            htmlBody += '<tr><td>' + TicketNumber + '</td><td>' + Sbj + '</td><td>' + HandlingTimeTarget + '</td><td>' + PIC + '</td><td><a href="https://cs72.salesforce.com/' + Link + '">Click Here</a></td></tr>';

            if (strOwnerEmail == null){
                strOwnerEmail = 'rieftjong95@gmail.com'; 
                mapOwnerEmailtoEmail.put(strOwnerEmail, htmlBody);
            }

            mapOwnerEmailtoEmail.put(strOwnerEmail, htmlBody);

        }
    }

    for(string strOwnerEmail : mapOwnerEmailtoCaseList.keyset()){

        system.debug('===strOwnerEmail===='+strOwnerEmail);
        string strHTML = mapOwnerEmailtoEmail.get(strOwnerEmail);
        strHTML += '</table><br><br><br><p>Terimakasih,</p><br><p>System Administrator</p>';
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); 

        List<String> sendTo = new List<String>();
        sendTo.add(strOwnerEmail);
        //mail.setTargetObjectId(sendTo);
        mail.setToAddresses(sendTo);
        mail.setSenderDisplayName('Administrator');
        mail.setSubject(subject);
        mail.setHtmlBody(strHTML);

        mail.setSaveAsActivity(false);
        listmail.add(mail);


        }
        Messaging.sendEmail(listmail);
    }

}

and this is the log

enter image description here

how to prevent the null value being inserted? or skip the null value? or this is not the problem?

3

This is a lot of code and maps to wade through, but it looks like all you need is one if condition in your first for loop:

for(Case objCase : [SELECT Id, Owner.Email, Status, Owner.Name, CaseNumber, CreatedBy.Name,Subject, OwnerId, SLA_Case_Closed_Days__c  FROM Case where Status != 'Closed']) {
    if (String.isNotBlank(objCast.Owner.Email)) {
         // all your existing logic goes here
    }
}

I suspect what's actually happening is that you have Cases that are owned by Queues rather than Users, and hence do not have an email address (a User would have an email). You can simply drop them this way, or you can include a filter on Owner.Type = 'User' in your query:

[SELECT Id, Owner.Email, Status, Owner.Name, CaseNumber, CreatedBy.Name,Subject, OwnerId, SLA_Case_Closed_Days__c  
 FROM Case 
 WHERE Status != 'Closed' AND Owner.Type = 'User']
  • I realized that my Owner field on case object = Lookup(User/queue) and there`s no email on my queue.. thanks! – Arief Gunawan Tjiptorahardja Jul 10 '18 at 15:44
0

You have to check if the email adress you're adding to the list is empty or not:

for(string strOwnerEmail : mapOwnerEmailtoCaseList.keyset()){
    if(strOwnerEmail != null){
        system.debug('===strOwnerEmail===='+strOwnerEmail);
        string strHTML = mapOwnerEmailtoEmail.get(strOwnerEmail);
        strHTML += '</table><br><br><br><p>Terimakasih,</p><br><p>System Administrator</p>';
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); 

        List<String> sendTo = new List<String>();
        sendTo.add(strOwnerEmail);
        //mail.setTargetObjectId(sendTo);
        mail.setToAddresses(sendTo);
        mail.setSenderDisplayName('Administrator');
        mail.setSubject(subject);
        mail.setHtmlBody(strHTML);

        mail.setSaveAsActivity(false);
        listmail.add(mail);
    }

}
0

An alternative to checking if an email is null before putting it into your map is to check for (and remove) a null value after you're done putting things into your map.

Map<String, String> myMapWithNull = new Map<String, String>{
    '1' => 'one',
    '2' => 'two',
    null => 'what\'s this?'
    '3' => 'three'
};

System.debug(myMapWithNull); // Should print [{'1' => 'one'}, {'2' => 'two'}, {null => 'what\'s this?'}, {'3' => 'three'}]... or something like that

myMapWithNull.keySet().remove(null);

System.debug(myMapWithNull); // Should print [{'1' => 'one'}, {'2' => 'two'}, {'3' => 'three'}]... or something like that

Using map.keySet() unsurprisingly gives you a set of the keys of the map.
Using the remove() method of the Set class, unsurprisingly, removes an element from the set.

The combination of map.keySet().remove() causes the specified key to be removed from the map, which basically causes the value to be removed from the map as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.