Bonjour à tous,

J’ai mis en place un moyen d’envoyer des alertes mails avec des composantes de temps et des conditions.
Par exemple :
Je veux envoyer une alerte mail trois mois après la création de d’un rdv si et seulement si l’ia n’a pas confirmé son rdv. Je veux relancer l’IA avec son manager en copie.

Cette exemple comporte plusieurs points :

- Les workflows ne sont pas disponibles sur la table des activités (événements et tâches)
- Les workflows permettent de faire des relances avec une composante de temps mais sans réévaluer la règle ni ajouter une condition.
- Salesforce limite les envois de mail via APEX à 1000 mails par jour.

Dans ce cas, où on ne peux pas envoyer de mail natif. La classe va permettre de le faire.
En APEX, en fonction des critères nous allons préparer un envoi de mails en masse, via les méthodes génériques de la classe MailTemp.
Cette même classe est schedulable donc un script sera inséré dans les tâches prévues afin de lancer les alertes mails à une heure choisie.

Passons maintenant sur un aspect un peu plus technique.
Les limitations notamment, cette classe à quelques inconvénients mineurs.
- On ne pourra pas mettre des destinataires en Cc (Copie carbone) ou Cci (Copie carbone invisible)
- La classe est limité à 50 Workflows actifs, soit 50 templates mails en quelque sorte. Je rappelle qu’en même temps normalement la plupart des alertes est faisable en natif.
- L’Apex ne prend pas en charge la réflection comme le fait JAVA ou le C#, de ce fait nous sommes obligés d’affecter chaque valeur à la main sans pouvoir faire de boucle … (Voir dans la classe l’affectation des mails et des fields dans la méthode PrepareMailGenerique) Si vous trouvez un moyen plus sexy je suis preneur !
D’autres limitations qui peuvent être, elles, modulables :
- 40 destinataire maximum par mail
- 30 champs texte de mapping disponible
Comme une classe est limitée à 500 champs customs on pourrait bien sûr, si besoin, améliorer la classe pour prendre en compte plus de mails ou de champs. Mais dans notre cas ce n’est pour le moment, pas nécessaire.
D’autres limites peuvent intervenir en cas d’envoi de mails en masse de plus de 2000 mails d’un coup. Dans ce cas je vous invite à (re)lire la documentation sur les limites.


L’utilisation maintenant :

La classe permet de stacker des mails , elle les insères en base. Une fois inséré, un workflow sur les insert se déclenche et envoi le mail avec le bon template.
La classe comporte un exemple commenté qui est EnvoiMailCom().
- Comment savoir si c’est le bon template ?
Le champ Name de l’objet va servir d’id.
Exemple : name = « MAIL_COMM »
Mon workflow aura comme conditions : Si Email1__c différent de vide ET Name == ‘MAIL_COMM’ alors OK
- Qu’advient-il des éléments insérés en base ?
Les éléments en base restent stockés. Par contre un champ case à cocher sur l’objet ‘Archive’ va permettre de voir si le mail est bien envoyé ou non.
C’est pour ça que le workflow en plus de l’alerte mail devra mettre à jour ce champs en ‘True’. Et comme on est jamais trop prudent on pourra rajouter cette condition dans la règle du workflow.
Pour reprendre l’exemple ci-dessous ça donnera : Si Email1__c différent de vide ET Name == ‘MAIL_COMM’ ET Archive différent de True alors OK
-Comment savoir comment faire le matching ? Les champs de matching sont en format string et j’ai des dates comment faire ?
La partie mapping est à vous de le gérer. Vous gérer votre alerte de façon à ce que tout coordonne.
Les champs sont tous en format string, à vous de les caster afin qu’il y ait pas de soucis.

Le prototype de la fonction de préparation :
Code JAVA : Sélectionner tout - Visualiser dans une fenêtre à part
public static list<TamponMail__c> PrepareMailGenerique(list<string> lmail, list<string> lfield, string nom, string objet, list<TamponMail__c> lTempMail)
Valeur de retour : Liste de mails (pour pouvoir les empilés)
Arguments :
- lmail : Liste de mails (40 éléments maxi), un élément de la liste == un mail.
- lfield : Liste des champs customs (30 éléments maxi), un élément de la liste == un champ à matcher dans le template du mail sur Salesforce.
- nom : Champ texte qui permet de gérer par la suite les workflows
- objet : champs texte qui représente l’objet du mail
- lTempMail : Pareil que la valeur de retour c’est pour pouvoir empiler les mails

Le prototype de la fonction d’envoi :
Code JAVA : Sélectionner tout - Visualiser dans une fenêtre à part
public static void EnvoiMailGenerique(list<TamponMail__c> tmail)

Valeur de retour : Aucune, elle clôture le traitement en envoyant intégralement la liste de mail, théoriquement lTempMail.
Argument :
- tmail : une liste permettant d’envoyer tous les mails. (Je conseille d’éviter de dépasser les 2000, après plusieurs tests le comportement au dessus de 2000 mail envoyé est aléatoire. Souvent Salesforce retourne une erreur interne)


Pour finir dans la méthode schedulable il faut mettre les méthodes qui envoient les mails et qui se servent des méthodes de la classe MailTemp.cls




Je mets à disposition un package regroupant la classe, l’objet et ses champs, afin de pas avoir besoin de tout créer sur sa sandbox pour faire des tests si besoin. https://test.salesforce.com/packagin...4tW00000004t2U

Voici la classe :
Code JAVA : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// Réalisé par Ludovic Marboutie le 03/01/2013
// Pour éviter de dépasser les limites de SF(1000 mail max par jour). La les mails sont déclenché par worklow sur la classe.
 
/* LIMITES :
				- Prend en charge 50 alertes mails (limite de workflow par classe)
				- Les champs customs sont limités à 30
					- Ils doivent être formaté en string donc à vous de concaténer comme il faut.
					- Attention au mapping.
				- Les mails insérés sont limités à 40
					- Attention ils apparaissent tous dans la zone "A:" donc pas possible de mettre en copie 
					les envois de mails seront tous destinataire. C'est le petit truc que j'ai pas réussi à faire.
				- Le Nom est là pour faire office d'id pour déclencher le bon workflow avec la bonne alerte mail et surtout le bon template.
				- L'objet c'est l'objet rien de particulier.
				- le dernier arguement de la methode prépare est pour empiler les envois de mail. 
*/
 
global class MailTemp implements Schedulable 
{	
	global void execute(SchedulableContext ctx)
	{
 
		//insérer tout les méthodes d'envoi de mail pour balancer une seule tache à 23h
		// Aucune traitement métier ne doit apparaitre dans cette classe afin de la garder le plus générique possible.
 
		//déclenche les méthodes métier qui se servent des méthodes de cette classe.
	   //  EnvoiMailCom();
	}	 
 
 
 
	public static list<TamponMail__c> PrepareMailGenerique(list<string> lmail, list<string> lfield, string nom, string objet, list<TamponMail__c> lTempMail)
	{
 
 
		TamponMail__c tmail = new TamponMail__c();
 
		//affectation d'un 'id' pour la reconnaissance de l'alerte par le workflow
			tmail.Name = nom;
			tmail.Objet__c = objet;
 
		//Note : La reflection en APEX n'est pas encore possible donc obligé de faire l'affectation à la main...
		//affectation des mails.
		if (lmail.size() > 0)
			tmail.Email1__c = lmail.get(0); 
		if (lmail.size() > 1)
			tmail.Email2__c = lmail.get(1);
		if (lmail.size() > 2)	
			tmail.Email3__c = lmail.get(2);
		if (lmail.size() > 3)	
			tmail.Email4__c = lmail.get(3);
		if (lmail.size() > 4)
			tmail.Email5__c = lmail.get(4);
		if (lmail.size() > 5)
			tmail.Email6__c = lmail.get(5);
		if (lmail.size() > 6)
			tmail.Email7__c = lmail.get(6);
		if (lmail.size() > 7)
			tmail.Email8__c = lmail.get(7);
		if (lmail.size() > 8)
			tmail.Email9__c = lmail.get(8);
		if (lmail.size() > 9)
			tmail.Email10__c = lmail.get(9);
		if (lmail.size() > 10)
			tmail.Email11__c = lmail.get(10);
		if (lmail.size() > 11)
			tmail.Email12__c = lmail.get(11);
		if (lmail.size() > 12)
			tmail.Email13__c = lmail.get(12);
		if (lmail.size() > 13)
			tmail.Email14__c = lmail.get(13);
		if (lmail.size() > 14)
			tmail.Email15__c = lmail.get(14);
		if (lmail.size() > 15)
			tmail.Email16__c = lmail.get(15);
		if (lmail.size() > 16)
			tmail.Email17__c = lmail.get(16);
		if (lmail.size() > 17)	
			tmail.Email18__c = lmail.get(17);
		if (lmail.size() > 18)
			tmail.Email19__c = lmail.get(18);
		if (lmail.size() > 19)
			tmail.Email20__c = lmail.get(19);
		if (lmail.size() > 20)
			tmail.Email21__c = lmail.get(20);
		if (lmail.size() > 21)
			tmail.Email22__c = lmail.get(21);
		if (lmail.size() > 22)
			tmail.Email23__c = lmail.get(22);
		if (lmail.size() > 23)
			tmail.Email24__c = lmail.get(23);
		if (lmail.size() > 24)
			tmail.Email25__c = lmail.get(24);
		if (lmail.size() > 25)
			tmail.Email26__c = lmail.get(25);
		if (lmail.size() > 26)
			tmail.Email27__c = lmail.get(26);
		if (lmail.size() > 27)
			tmail.Email28__c = lmail.get(27);
		if (lmail.size() > 28)
			tmail.Email29__c = lmail.get(28);
		if (lmail.size() > 29)
			tmail.Email30__c = lmail.get(29);
		if (lmail.size() > 30)
			tmail.Email31__c = lmail.get(30);
		if (lmail.size() > 31)
			tmail.Email32__c = lmail.get(31);
		if (lmail.size() > 32)
			tmail.Email33__c = lmail.get(32);
		if (lmail.size() > 33)
			tmail.Email34__c = lmail.get(33);
		if (lmail.size() > 34)
			tmail.Email35__c = lmail.get(34);
		if (lmail.size() > 35)
			tmail.Email36__c = lmail.get(35);
		if (lmail.size() > 36)
			tmail.Email37__c = lmail.get(36);
		if (lmail.size() > 37)
			tmail.Email38__c = lmail.get(37);
		if (lmail.size() > 38)
			tmail.Email39__c = lmail.get(38);
		if (lmail.size() > 39)
			tmail.Email40__c = lmail.get(39);
 
		//Note : La reflection en APEX n'est pas encore possible donc obligé de faire l'affectation à la main...	
		//affectation des champs custom
		if (lfield.size() > 0)
			tmail.field1__c = lfield.get(0); 
		if (lfield.size() > 1)
			tmail.field2__c = lfield.get(1);
		if (lfield.size() > 2)
			tmail.field3__c = lfield.get(2); 
		if (lfield.size() > 3)
			tmail.field4__c = lfield.get(3);
		if (lfield.size() > 4)
			tmail.field5__c = lfield.get(4); 
		if (lfield.size() > 5)
			tmail.field6__c = lfield.get(5);
		if (lfield.size() > 6)
			tmail.field7__c = lfield.get(6); 
		if (lfield.size() > 7)
			tmail.field8__c = lfield.get(7);
		if (lfield.size() > 8)
			tmail.field9__c = lfield.get(8); 
		if (lfield.size() > 9)
			tmail.field10__c = lfield.get(9);
		if (lfield.size() > 10)
			tmail.field11__c = lfield.get(10); 
		if (lfield.size() > 11)
			tmail.field12__c = lfield.get(11);
		if (lfield.size() > 12)
			tmail.field13__c = lfield.get(12); 
		if (lfield.size() > 13)
			tmail.field14__c = lfield.get(13);
		if (lfield.size() > 14)
			tmail.field15__c = lfield.get(14); 
		if (lfield.size() > 15)
			tmail.field16__c = lfield.get(15);
		if (lfield.size() > 16)
			tmail.field17__c = lfield.get(16); 
		if (lfield.size() > 17)
			tmail.field18__c = lfield.get(17);
		if (lfield.size() > 18)
			tmail.field19__c = lfield.get(18); 
		if (lfield.size() > 19)
			tmail.field20__c = lfield.get(19);
		if (lfield.size() > 20)
			tmail.field21__c = lfield.get(20); 
		if (lfield.size() > 21)
			tmail.field22__c = lfield.get(21);
		if (lfield.size() > 22)
			tmail.field23__c = lfield.get(22); 
		if (lfield.size() > 23)
			tmail.field24__c = lfield.get(23);
		if (lfield.size() > 24)
			tmail.field25__c = lfield.get(24); 
		if (lfield.size() > 25)
			tmail.field26__c = lfield.get(25);
		if (lfield.size() > 26)
			tmail.field27__c = lfield.get(26); 
		if (lfield.size() > 27)
			tmail.field28__c = lfield.get(27);
		if (lfield.size() > 28)
			tmail.field29__c = lfield.get(28);
		if (lfield.size() > 29)
			tmail.field30__c = lfield.get(29);
 
		lTempMail.add(tmail);		
		return lTempMail;
	}
	public static void EnvoiMailGenerique(list<TamponMail__c> tmail)
	{
		//permet d'envoyer tout d'un bloc sans pour autant exploser les limites. 
		insert tmail; 
	}
 
 
	//methode de couverture 
	static  testmethod void testMailTemp()
	{
		TamponMail__c tmail = new TamponMail__c();
		list<string> lmail = new list<string>();
		list<string> lfield = new list<string>();
		list<TamponMail__c> lTempMail = new list<TamponMail__c>();
		string nom;
		string objet;
 
		//injecter 40 mails
		for (Integer i = 0; i < 40; i++)
			lmail.add('MailTest' + i + '@test.com');
		//injecter 100 champs customs
		for (Integer i = 0; i < 30; i++)
			lfield.add('champs custom' + i);
 
		objet = 'test sandbox ';
		nom = 'ID_WORKLOW_TEST';
 
		lTempMail = PrepareMailGenerique(lmail, lfield, nom, objet, lTempMail);
		EnvoiMailGenerique(lTempMail);
 
	}	
 
 
 
 
	//methode de test.
/*	public static void EnvoiMailCom()
	{	
		TamponMail__c tmail = new TamponMail__c();
		list<string> lmail = new list<string>();
		list<string> lfield = new list<string>();
		list<TamponMail__c> lTempMail = new list<TamponMail__c>();
		string nom;
		string objet;
 
		for (Integer i = 0; i < 2000; i++)
		{
			nom = 'AM_RDV_A_VALIDER';
			lmail.add('test@test.com');
			objet = 'test sandbox : ' + i;
			lfield.add('test description');
			lfield.add('12/12/2012 00:00');
			PrepareMailGenerique(lmail, lfield, nom, objet, lTempMail);
		}
			EnvoiMailGenerique(lTempMail);
	}*/
}

Je l'ai testé avec 2000 mails ça passe niquel.
Il se peut qu'il y est quelques exceptions non géré, c'est la version beta :p