You need to sign in to do that
Don't have an account?
larkinrichards
Behavior testing a sendEmail statement
Hi, I'm wondering how I can write an assertion in a test method that shows that an email was sent. I have code that sends an email if certain criteria are met, but does not do any updates to the object in question. If the only outcome from the code firing is that an email is sent, how can I verify that the email was sent?
I understand that if I wrap the test like so:
test.startTest(); insert aCase; test.stopTest();
Then the stopTest() should make all asynchronous tasks run - including sendEmail. My question is, how do I query the send email log in a test method to assert it sent the email?
Thanks in advance!
you have a method in Messaging.SendEmailResult Object called isSuccess.. u can make use of this.. to check whether mail was sent r not .. this can be used in system.assert .....
Thanks Kiran, unfortunately that requires rewriting methods just to test them and while it is useful for unit testing, I wanted to do a behavior test of a full user interaction.
I ended up looking at the EmailUtil code from the CodeShare and rewrote it as a wrapper for the base email methods, with enhancements that make it easier to bulkify a trigger, and some public static variables that can be accessed in a test to verify outcomes.
I'm tidying it up a bit and then I'll submit it to CodeShare/Post it here.
Here's some pseudo code representing a simple behavior and a test for that behavior with the revised EmailUtil:
Here's the full code of the updated utility, and some tests.
I'd love to hear feedback on the code - hit me up here and I'll happily revise it.
Test fails at line 263: List has no rows for assignment to SObject. This is the line -
Folder test_template_folder = [Select Id from Folder Where Type = 'Email' And IsReadOnly = false Limit 1];
I guess because I need to add a Folder of type Email?
I added a new Folder and now the Test completes with the result 3 lines not tested:
public EmailUtil whatId (Id an_id) {
whatId = an_id;
return this;
}
Hi Carlo,
Thanks for noting those bugs. I recall that I wasn't able to create an email template folder via apex and so I had to do that manually prior to testing. I'm not sure if there is a better way to populate test data for email templates-- if anyone has suggestions for how to improve the test so that it doesn't require test data that would be great.
Also, re: the 3 lines not being tested: As each organization could have data validation rules or other things which would prevent a test object from being inserted, I wasn't sure the best way to test that line. AFAIK there isn't a way to create mock objects in apex.
I have just tried using the replyTo option. It does not seem to work. It just uses the email address setup for the user who sends the email. I want to to use a system type address like noreply@ourcompany.com. I added
.replyTo('noreply@ourcompany.com')
Am I missing something.
Thanks
Carlo
Hi Carlo,
Interesting... I just tested this and it sets the reply-to address correctly, but Gmail is not respecting the reply-to address. When I try to reply to the email address in Outlook, it works fine. Are you using Gmail, Outlook, or a different mail client?
Best,
Pete
For more details on my steps to recreate, read on:
I just ran the following anonymous apex(with email addresses substituted):
And here's the applicable section of the email header(again, with email addresses substituted):
In Gmail, when I press reply, it replies to "myname@mydomain.org" and not "absolutelynoreply@mydomain.org"
In Outlook, when I press reply, it replies to "absolutelynoreply@mydomain.org"
I have tried it on Hotmail web, Gmail web and my Mac Mail client. All do not work.
It would help if I can review the code-- Can you recreate the issue with an anonymous apex snippet and post that snippet here? Or, if it's easier for you, just post the code you're using.
I just copied your code and changed the 2 email addresses and executed it as anonymous apex. The address I am sending to is my Hotmail addess. When I receive the email in Hotmail it shows my normal SF email address. There is no mention of the noreply address anywhere.
I dont believe its your code thats the problem. I'm thinking its a SF thing.
Edit
When I recieve the email into my web based Gmail it shows the email as coming from my normal SF address via some long weird SF address. When I hit reply it uses the absolutelynoreply address.
Similarly in Hotmail. When I hover over the sender's name 'my name' it displays my normal SF email in a pop up. When I hit reply it does use the absolutelynoreply address.
Okay, that sounds correct-- if you check the email headers you'll see that "Reply-To" is getting set correctly. Reply-To doesn't override the From header, but when you reply it should reply to the Reply-To address.
If you want the From address to show "noreply," then you should use an organization wide email address to send the email. Unfortunately, the emailUtil above does not have code for using an organization wide email address.
Best,
Pete
I have added owa support to your utility class. There is an extra option for OrgWideEmailAddress. If the user enters one it searches for it in the owa records which already exist and if it finds a match it uses the ID of the object to attach it to the email. I have also added a test for this. The test will only run if there is an owa added to the org. I could not add one using DML in the test.
Edit - I am hitting a 20,000 character limit trying to paste this into here. Any ideas?
Pete
Sorry to bother you again. I'm trying to use the sendEmail util with a Template. I am getting the following error:
System.EmailException: SendEmail failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Missing targetObjectId with template: []: Class.EmailUtil.sendEmail: line 172, column 1
I am using sendEmail like this:
emailUtil.to(toAddresses)
.templateId('00XQ0000000MKEz')
.sendEmail();
How do I use a template with sendEmail?
Thanks
Carlo
I figured this out if anyone is interested. You have to use a target ID when using a template rather than an email address.
emailUtil.to(ContactId)
.templateId('00XQ0000000MKEz')
.whatId(CampaignId)
.sendEmail();