Direkt zum Hauptbereich

Email Versand

Mit einer interessanten, aber auch ziemlich komplizierten Aufgabe habe ich mich in den letzten Tagen beschäftigt.
Aufgabenstellung: sobald ein Ticket(Case) eine Eskalationsstufe erreicht, müssen alle relevanten Benutzer per Email informiert werden.

Eigentlich ganz einfach, dachte ich. Die Lotus Notes Platform bietet in Bezug auf die Email-Generierung und Versand vielfältige Möglichkeiten. Mit Salesforce sind die Grenzen klar definiert.

Nun zur Umsetzung:
1) Einen Trigger programmiert, der beim Aktualisieren von Cases die Methode "informUsersOnCaseEscalation()" aus der "helper" Klasse aufruft.

trigger CaseTrigger on Case (before insert, before update) {
 //BEFORE INSERT or UPDATE
 if(Trigger.isBefore){
  //... initialize ...
  CaseTriggerHelper helper = new CaseTriggerHelper(Trigger.new, Trigger.oldMap);
  if(Trigger.isUpdate){
   helper.informUsersOnCaseEscalation(); //send mass email to queue members on case escalation
  }
 }
} 

2) Ich verzichte auf die Darstellung und Beschreibung des Konstruktors aus der helper-Klasse und zeige nur die für den Email-Versand relevanten Ausschnitte.

Die folgende Methode baut eine Liste mit Emails zusammen und versendet diese anschließend.


public void informUsersOnCaseEscalation(){
 List<Messaging.SingleEmailMessage> emailsSingle = new List<Messaging.SingleEmailMessage>();
 String Errors = '';

 for(Case c : lstCases){
  if(escalationLevel > 0){
   emailsSingle.add(NewSingleEmail(lstRecipients, c));
  }
 }
 if(!emailsSingle.isEmpty())
  sendEmailsSingle(emailsSingle);
}


Warum SingleEmailMessage und nicht MassEmailMessage?
Ohne sich ausreichend mit der Doku zu beschäftigen, habe ich angefangen, zu programmieren. Ist ja logisch, einfacher Email-Versand. Wer braucht da schon die Doku ;-)
Da die Anzahl der Email-Empfänger unbekannt ist, habe ich mich für die MassEmailMessage (MEM) Methode entschieden, außerdem bringt sie einige Features mit, die ich brauche.
Zum Beispiel, es gibt ein Email Template mit dem vorkonfigurierten Text, der auch Formeln enthält. Dieses Template soll benutzt werden.
Während der Umsetzung stellte ich fest, dass die MEM Methode nicht geeignet ist.

Und hier sind die Gründe:
a) die Formeln aus dem Email Template werden vom System entfernt, weil die Verbindung zu Cases nicht hergestellt werden kann:
Mit setTemplateID teile ich dem System das Email Template mit.
Mit setTargetObjectIds werden die Empfänger bekannt gegeben.
Mit setWhatIds stelle ich die Verbindung zu Cases <- und genau hier klemmt es. Dieser Parameter lässt sich nur dann benutzen, wenn man Emails an Kontakt-Objekte adressiert (und nicht an User-Objekte).
zu a) Man könnte temporär Kontakte erzeugen, die Email-Adressen aus den User-Objekten übertragen, Emails versenden und dann die Kontakte löschen. Eine sehr traurige Angelegenheit. Zudem werden solche Aktionen im Chatter protokolliert: "Neuer Kontakt erstellt..."

b) Eine andere Möglichkeit wäre, Email-Subject und Body aus dem Template übernehmen und alle Platzhalter durch gültige Werte ersetzen.
zu b) Leider auch unmöglich. Die MEM Methode ermöglicht das Befüllen von Subject (von Salesforce undokumentiert), aber nicht das Befüllen des Body-Feldes.

Folgend ist die implementierte SingleEmailMessage Methode (SEM). Diese Methode ist etwas mächtiger. Hier müssen allerdings SMTP-Email-Adressen benutzt werden, anstatt von UserIDs. Diese lassen sich aber per SOQL Query berechnen.


/***** NewSingleEmail() *****/
/*+++++++++++++++++++++++++++++++++++++++++++++++++*/
private Messaging.SingleEmailMessage NewSingleEmail(List<Id> lstRecipients, Case caseObj){
 //Build a list with all Email Addresses to send emails to
 List<String> lstEmailAdr = new List<String>();
 for(Id idUser : lstRecipients){
  String emailAdr = mapQueueMemberEmails.get(idUser);
  lstEmailAdr.add(emailAdr);
 }
 // Build EMAIL -----------------------------------------
 Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
 mail.setUseSignature(false);
 mail.setSaveAsActivity(false);
 mail.setToAddresses(lstEmailAdr);
 setSubjectAndBody(mail, caseObj);

 return mail;
}


Da das Email Template einige Formeln enthält, lassen sich diese mit Hilfe von regular expressions finden und ersetzen. Und damit werden Subject und Body gesetzt:

***** setSubjectAndBody() *****/
/*+++++++++++++++++++++++++++++++++++++++++++++++++*/
private void setSubjectAndBody(Messaging.SingleEmailMessage mail, Case caseObj){
 // Subject and Body of Email Template
 String sSubjectOut = emailTemplateEscalation.Subject;
 String sBodyOut = emailTemplateEscalation.Body;

 // Regex pattern to get Field Names from Email Template
 Pattern p = Pattern.compile('\\{([^}]*)\\}');
 String caseField;
 String replaceWhat;
 String replaceWith;

 //Build SUBJECT -----------------------------------------
 Matcher m = p.matcher(sSubjectOut);
 while (m.find()){
  caseField = m.group(1);
  caseField = caseField.substringAfter('.');
  replaceWhat = '{!Case.' + caseField + '}';
  replaceWith = String.valueof(caseObj.get(caseField));
  sSubjectOut = sSubjectOut.replace(replaceWhat, replaceWith);
 }

 //Build BODY -----------------------------------------
 m = p.matcher(sBodyOut);
 while (m.find()){
  caseField = m.group(1);
  caseField = caseField.substringAfter('.');
  replaceWhat = '{!Case.' + caseField + '}';

  if(caseField == 'Link') replaceWith = URL.getSalesforceBaseUrl().toExternalForm() + '/' + caseObj.Id;
  else if(caseField == 'OwnerFullName') replaceWith = mapQueueMembersNames.get(caseObj.OwnerId);
  else replaceWith = String.valueof(caseObj.get(caseField));

  if(replaceWith == '' || replaceWith == null) replaceWith = caseField;

  sBodyOut = sBodyOut.replace(replaceWhat, replaceWith);
 }
 mail.setSubject(sSubjectOut);
 mail.setPlainTextBody(sBodyOut);
}



Kommentare

Beliebte Posts aus diesem Blog

Salesforce - Datensätze sperren (Umsetzung)

Record Lock - nun, die Umsetzung.Wir haben bereits mehrere VisualForce Pages im Einsatz. Aus dem Grund ist das zuvor beschriebene Konzept darauf zugeschnitten. Selbstverständlich lässt sich der Code auch für Standard und Custom Objects verwenden, ohne den Einsatz von VisualForce Pages. Na ja, mindestens eine VF Page brauchen wir eigentlich schon - diejenige, die von dem dem "Edit" Button aufgerufen wird.

Ich zeige jetzt die wichtigsten Bausteine aus der Umsetzung.
1) Diese VF Page wird aufgerufen sobald man den "Edit" Button betätigt

<apex:pagestandardController="myObject"title="{!myObject.Name}"extensions="LockController"action="{!SwitchToPage}">
<!-- READ MODE --> <apex:includepageName="myObjectRead"rendered="{!isEditMode == false}"/>
<!-- EDIT MODE --> <apex:includepageName="myObjectEdit"rendered="{!isEditMode == true}"/>
</apex:page>

Folgendes passiert …

Salesforce.com Certified Advanced Administrator (WI15)

Im Vergleich zu den beiden Consultants Zertifizierungen war die Advanced Admin ein Spaziergang!
Allerdings ganz ohne Vorbereitung schafft man die Prüfung auch nicht.


Hier sind einige Fragen/Antworten aus der aktuellen Prüfung.

1. Capabilities of collaborative forecasting?
- Rename categories
- Forecast using opportunity splits
- Overlay Quota
- Add categories
- Select a default forecast currency setting

2. We have four Sales Regions. Each of the region's VPs wants to have a dashboard emailed every Monday.
- Create a separate dashboard for each VP
- Create one dashboard using Visualforce
- Create one dashboard that includes a filter for each region
- Create a reporting snapshot

3. User is trying to access content in a library, but receiving an insufficent privileges message.
How to troubleshoot?
- has the user's profile the CRM content permission enabled
- user has been granted permission "Viewer" to the library
- user's record has the CRM content permisson enabled
- …

Emails mit APEX | SINGLE_EMAIL_LIMIT_EXCEEDED

Email-Versand mit Visualforce und Apex kann schon manchmal Kopfschmerzen bereiten....

Entweder ist die Email zu groß, oder zu viele Attachments oder der HeapSize "beschwert sich" oder, wenn letztendlich alles läuft,  man wird von den Salesforce Limits zurück zum Ausgangspunkt katapultiert.

Das kann doch nicht so schwer sein!
Ist es auch nicht, wenn man das schon einmal gemacht hat ;-)

Habe eine Visualforce Maske zum Versenden von HTML Emails programmiert.
Diese werden als SingleEmailMessage gesendet:
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
Sobald die Anzahl der pro Tag gesendeten Emails den Salesforce Limit "knackt", wird dem User die entsprechende Meldung eingeblendet.



Die auf die Org bezogene Limitierung lässt sich mit LIMITS.getLimitEmailInvocations() berechnen.

Hier ein Auszug aus den "Execution Governors and Limits"
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm

A Dev Edition org ha…