5

Problem Statement

I'm working on a fluent email builder, but I've hit a bit of a snag. Namely, there does not seem to be any simple way to completely clone a Messaging.SingleEmailMessage instance without sharing a reference.

Why would I want to do such a thing? Well, it seems pretty common to have a collection of emails with common properties such as subject, recipients, template, etc.

Attempts

Serialization

The simplest attempt code-wise would be to serialize and de-serialize to break the reference:

Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
Messaging.SingleEmailMessage clone = (Messaging.SingleEmailMessage)
    JSON.deserialize(JSON.serialize(email), Messaging.SingleEmailMessage.class);

However, this code throws a run-time error:

System.JSONException: Unrecognized field "debug" at [line:1, column:83]

Apparently it is not even possible to re-serialize back to the same type here!

Getters/Setters

Fine, I thought, I'll just use all of the getters and manually copy over each property:

Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
// set various properties

Messaging.SingleEmailMessage clone = new Messaging.SingleEmailMessage();
clone.setBccAddresses(message.getBccAddresses);
// and so on

However, a couple Boolean flags on this object lack getters:

Method does not exist or incorrect signature: [Messaging.SingleEmailMessage].getTreatBodiesAsTemplate()

Method does not exist or incorrect signature: [Messaging.SingleEmailMessage].getTreatTargetObjectAsRecipient()

Question

Is there any simple or elegant way to clone a Messaging.SingleEmailMessage instance? I'm pursuing other design routes (like making the builder virtual) but it's frustrating to not be able to clone such a basic system object. The only way I can think to do it would be to pull out the properties from an untyped map, which is not a satisfying long term solution:

Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
Map<String, Object> data = (Map<String, Object>)
    JSON.deserializeUntyped(JSON.serialize(email));
Boolean treatBodiesAsTemplate = data.get('treatBodiesAsTemplate');
Boolean treatTargetObjectAsRecipient = data.get('treatTargetObjectAsRecipient');
  • Well, not sure about cloning but the TreatTargetObjectAsRecipient and TreatBodiesAsTemplate boolean flags are public and can be accessed by email.TreatBodiesAsTemplate. – Santanu Halder Apr 19 '17 at 18:17
  • 1
    Ah, that's strange they have a different access pattern...wasn't aware of that. That's good enough for my purposes, and I would be happy to accept that as an answer. – Adrian Larson Apr 19 '17 at 18:23
  • yup, been there, faced that! Anyway, glad I was of help. :) – Santanu Halder Apr 19 '17 at 18:29
3

Regarding your getter/setter approach, the TreatTargetObjectAsRecipient and TreatBodiesAsTemplate boolean flags are having public access modifier and can be accessed as follows:

Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
Boolean treatBodiesAsTemplate = email.treatBodiesAsTemplate;
Boolean treatTargetObjectAsRecipient = email.treatTargetObjectAsRecipient;

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.