4

I suspect the answer here is "No", but I thought I'd ask anyway. Can I send an email, using a VFTemplate, to an arbitrary email address, as opposed to a Contact, User, or Lead?

I need to send a fairly complex email, which will require a VF email template. All merge fields in the template will come from the relatedTo object (case), nothing from recipient. These emails will be sent to an email-to-fax service, where the email-to-fax address is stored in a custom field on an account. When creating the email template in the UI, the options for Recipient Type are Contact, User, and Lead. And the documentation for SingleEmailMessage.setTargetObjectId() says "Required if using a template, optional otherwise".

So, do I have any option besides creating a "dummy" contact on the affected accounts to stor the email-to-fax email address?

5

No there's not - it has to be a record in the system, and it has to be a Contact/User/Lead and not a custom object. I recently found this out the hard way.

You can send emails to any address via Apex, but you can't reference VF templates directly that way. For HTML emails like this, I often use Apex and have a class which is specifically designed to create and handle the HTML for me.

4

It turns out there is a way to do this that I learned from John Conners. You can set the relatedTo as your user, and then setToAddresses/setBCCAddresses/setCCAddresses.

This causes any merge fields related to the recipient to be filled in with your user (or some dummy user/contact/lead)'s data, but if that doesn't matter for your use case this can be particularly useful - especially for sending a templated email to multiple addresses.

This only works with visualforce email templates.

Example code that will send to your user's email address, as well as example@example.org:

Id templateId = '00Xd0000000Y058';
Id someAccount = '001d000001MMNin';
Messaging.singleEmailmessage em = new Messaging.singleEmailMessage();
em.setTemplateId(templateId);
em.setTargetObjectId(UserInfo.getUserId());
em.setWhatId(someAccount);
em.setSaveAsActivity(false);
em.setToAddresses( new List<String>{ 'example@example.org' } );
Messaging.sendEmail( new List<Messaging.Email>{em} );

It comes across looking like this:

enter image description here

  • Hmm. set relatedTo or recipient? relatedTo is the case (set via setWhatId), so I'd need to set the recipient via setTargetObjectId(UserInfo.getUserId()). But, will this still send an email to the user, or only to the address(es) set via setToAddresses? And any issues doing this from inside a Trigger? Feedback requested, but I'll probably give this a try in an org. – Jason Clark Oct 11 '13 at 22:51
  • Docs for SingleEmailMessage.setToAddresses() claim, "This argument is allowed only when a template is not used." No time to test at the moment, but looking grim for Mudville. – Jason Clark Oct 11 '13 at 22:56
  • Apex email APIs have a huge amount of undocumented behaviors. You're right that you'd have to send email to a user in the process, but that can be any user, it doesn't have to be the running user. – ca_peterson Oct 11 '13 at 23:07
  • Just edited the answer with sample code and proof it works, even if it's an ugly hack for not having a better email API. – ca_peterson Oct 11 '13 at 23:09
  • 1
    Works with a contact instead of a user; specifically works with a contact that has an @example.com email address, which is reserved (tools.ietf.org/html/rfc2606) and won't go anywhere. I don't know if there are any concerns sending email to an unreachable email address. – Jason Clark Oct 14 '13 at 13:45
1

I just wrote a blog posting on a semi-related topic. http://www.techplustalk.com/2013/10/custom-mail-merge.html

Essentially, my use-case was to use email addresses stored in custom object records and then merge different data into an email template. I used a custom object (Email__c) with a rich-text field to define my HTML email content (complete with "fake" merge fields) and then when constructing each message in my apex controller, I replace the "fake" merge fields with the data that I want.

        // create email for each application (each applicant) that satisfies criteria
        for (Application__c app : appList) {
            Email__c e = emails.get(0);  // get applicable "template"

            Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
            email.setToAddresses(new String[] { app.Email__c });  // set email address from application
            email.setSenderDisplayName('CARPOOL - TAMU');  // can set any name here
            email.setSubject(e.Subject__c);

            // 'hack' to replace the merge fields with values from custom object
            String body = e.Body__c.replace('{!app.name}', app.First_Name__c);

            email.setHtmlBody(body);  // rich text field is actually html content 

            // add email to emailList -- this list will hold all the emails to be sent
            emailList.add(email);
        }

        // send all individual emails using one sendEmail call
        List<Messaging.SendEmailResult> results = Messaging.sendEmail(emailList);

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.