8

Can we send SingleEmailMessage(s) under admin context and ignore current user sharings and profile access. Details: - visualforce email template is related to object B which is not available for users in particular profiles. user in these profiles has access to object A and editing this object A can initiate sending email based on template related to forbidden/hidden object B. As result email sending fails.

I tried the following code:

  public without sharing class  ToDelete {
   public static void sendEmail(){
    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage ();
    mail.setTargetObjectId('00520000001r17P');//admin
    mail.setTemplateID('00XR0000000INj2');//VF email template related to Object B
    mail.setSaveAsActivity (false);
    mail.setWhatId('a0DR0000004PxQp');//=object B id
    mail.settoAddresses(new String[] {'test@test.com'});
             //mail.setorgWideEmailAddressId(General_Settings__c.getInstance().Org_Wide_Email_Address__c);
    system.debug('---- ' + mail);
    List<Messaging.SendEmailResult>  results = Messaging.sendEmail(new Messaging.Email[]{mail});
    system.debug('---- ' + results);
 }}

and run unit test:

 @IsTest(SeeAllData=true)
 private class ToDeleteTest {
  static testMethod void verify() {
    Id userId = '00520000001r17P';

    User u = [select id from User where id = :userId   limit 1];
    SYstem.runAs(u){
        ToDelete.sendEmail();        
  }
} 

This test runs with the following error:

 System.EmailException: SendEmail failed. First exception on row 0; first error: UNKNOWN_EXCEPTION, Read access denied for ObjectB__c: []

When I set read access on object B for user profile then test execution is sucessful

  • The Error you is just the tip of the iceberg I see more salesforce.com/us/developer/docs/apexcode/Content/… settoAddress cannot be used in conjunction with templateID and @crmprogdev pointed harcoding is not a good idea at all, you may be able to verify things in your sandbox but would fail if the user ID is different when migrating to another box/PRD – Rao Jun 11 '13 at 18:51
1

First, it's not a good idea to hard code an Id into a test class. Instead, its much better to create the user by querying for the profile you want to use or cloning them by querying for the profile you want to use, creating them, then using the new user for the "run as" user. Here's an example:

@IsTest(SeeAllData=true)
private class ToDeleteTest {
static testMethod void verify() {

Profile p = [SELECT id FROM profile WHERE name = 'Admin User'];
User u = new User(alias = "tstusr1', email = 'tstusr1@tstusr1.com', emailencodingkey='UTF-8', lastname = 'Tst1', languagelacalekey = 'en_US', localesidekey='en_US', profileid = p.Id, country='United States', timezonesidkey='America/NewYork', username='tstusr1@tstusr1.com');

insert u;

Test.startTest

   System.runAs(u){
      ToDelete.sendEmail();
      // Add system.debug statement(s) here to diagnose any problems
   }

Test.stopTest
// Add any test validation here to confirm email was sent 
} 

I would then add some kind of system.debug statement following the ToDelete.sendEmail(); statement to help further diagnose the source of the problem you're having. You'll notice that I've added Test.startTest and Test.stopTest code to isolate the actual test from the preparation of the user data. As part of "best practices", I'd suggest incorporating some kind of validation code to confirm the email was actually sent following the Test.stopTest, but that decision is up to you.

0

Have you thought about using a custom component in the VF email template - where that custom component refers to a custom controller?

The custom controller will run in system context and should have access to both A and B

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.