Nous voici arrivés au cinquième et dernier volet de notre série dédiée à la programmation des Entrées/Sorties (I/O) à bas niveau dans SAS. Si vous avez suivi les épisodes précédents, vous savez désormais utiliser des fonctions comme FOPEN, FREAD ou FGET pour manipuler des fichiers externes avec une précision chirurgicale.
Aujourd'hui, nous allons détourner ces mêmes fonctions pour accomplir une tâche bien différente, mais vitale pour l'automatisation de vos processus : envoyer des alertes e-mail directement depuis votre code SAS.
Imaginez qu'à la fin de son exécution (qui a duré 3 heures pendant la nuit), votre programme vous envoie un e-mail avec le statut du traitement, ou qu'il alerte automatiquement l'équipe support si une table est introuvable. C'est exactement ce que nous allons coder.
1. Le secret de SAS : Un e-mail n'est qu'un fichier texte
Pour SAS, écrire un e-mail ou écrire dans un fichier texte brut, c'est presque la même chose. La seule différence réside dans la méthode d'accès (le device ou engine) que l'on déclare dans notre fonction FILENAME.
Au lieu de pointer vers un chemin réseau (comme C:\temp\fichier.txt), nous allons utiliser la méthode d'accès spéciale EMAIL.
Dès lors, la logique de bas niveau s'applique à la lettre :
- On ouvre l'e-mail avec
FOPEN. - On écrit le corps du message avec
FPUT. - On expédie le message avec
FWRITE. - On ferme proprement avec
FCLOSE.
2. Exemple Pratique : Le notificateur de fin de traitement
Imaginons que nous avons une variable macro globale nommée STATUT_TRAITEMENT qui contient soit la valeur "OK", soit un message d'erreur. Nous allons écrire une étape DATA _NULL_ qui lit ce statut et envoie un e-mail personnalisé au responsable opérationnel.
Voici le code détaillé et entièrement francisé :
SAS
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
data _null_;
/* 1. Déclaration des variables de travail */
length code_statut $ 40
code_retour 8
id_fichier 8;
/* 2. Configuration de l'e-mail via la fonction FILENAME */
/* - Le 1er argument est notre fileref logique ('mon_mail')
- Le 2ème est l'adresse du destinataire principal
- Le 3ème est la méthode d'accès : 'EMAIL'
- Le 4ème contient les options, comme le sujet du message */
code_retour = filename('mon_mail',
'responsable.ops@entreprise.fr',
'email',
'subject="Notification : Fin du programme SAS"');
/* 3. "Ouverture" du message (mode écriture) */
/* Le livre laisse le second argument vide pour l'option par défaut,
mais c'est un mode output implicite */
id_fichier = fopen('mon_mail', ' ');
if id_fichier = 0 then do;
putlog "ERREUR: Impossible d'initialiser l'envoi d'e-mail.";
stop;
end;
/* 4. Récupération dynamique du statut via la macro-variable */
code_statut = symget('STATUT_TRAITEMENT');
/* 5. Rédaction conditionnelle du corps du message via FPUT */
if code_statut = 'OK' then do;
code_retour = fput(id_fichier, 'Bonjour,');
code_retour = fput(id_fichier, ' '); /* Ligne vide */
code_retour = fput(id_fichier, 'Le traitement nocturne s est terminé avec succès.');
end;
else do;
code_retour = fput(id_fichier, 'ALERTE CRITIQUE :');
code_retour = fput(id_fichier, 'Le programme a échoué avec l erreur suivante :');
code_retour = fput(id_fichier, code_statut);
end;
/* 6. Expédition de l'e-mail ! (C'est FWRITE qui déclenche l'envoi) */
code_retour = fwrite(id_fichier);
/* 7. Fermeture et libération de la mémoire */
code_retour = fclose(id_fichier);
putlog "NOTE: Tentative d'envoi d'e-mail terminée.";
stop;
run;
Décryptage de l'exemple :
- Le pilotage par la donnée : Remarquez comment la logique métier (
if/else) contrôle complètement le contenu du message. De la même manière, l'objet de l'e-mail, les destinataires ou les éventuelles pièces jointes pourraient être contrôlés par votre logique de programmation. - La fonction
SYMGET: Très pratique dans ce contexte, elle permet de récupérer la valeur d'une variable macro directement dans une étape DATA en cours d'exécution. - Le rôle de
FWRITE: En programmation fichier classique,FWRITEécrit une ligne dans le fichier physique. Avec l'accèsEMAIL, appelerFWRITErassemble le contenu du buffer (construit avec lesFPUT) et ordonne au serveur SMTP d'expédier le paquet.
3. Aller plus loin : Les options de configuration
La puissance de la fonction FILENAME avec la méthode EMAIL réside dans son 4ème argument (les options). Vous pouvez y passer des directives très précises, identiques à celles que l'on trouverait dans une instruction FILENAME classique.
Voici les options les plus utiles à connaître:
TO=: L'adresse (ou la liste d'adresses) du destinataire principal (comme vu dans notre exemple).FROM=: L'adresse e-mail de l'expéditeur (idéal pour définir une adresse générique typene-pas-repondre@entreprise.fr).CC=/BCC=: Pour gérer les copies et copies cachées.ATTACH=: Pour joindre un fichier (par exemple, le journal de log ou un export CSV).
4. Une limite à connaître : Le format HTML
La méthode d'accès EMAIL native (telle qu'utilisée avec les I/O de bas niveau) est conçue uniquement pour envoyer du texte brut. Vous ne pouvez pas insérer directement des balises HTML complexes (couleurs, gras, tableaux) via les fonctions FPUT.
Si vous devez envoyer un rapport formaté en HTML, l'approche recommandée est d'utiliser l'ODS (Output Delivery System) pour générer votre document HTML, puis de l'envoyer en pièce jointe via cette méthode d'e-mail, ou de passer par des scripts applicatifs externes.
Conclusion de notre série
Nous voici à la fin de notre exploration de la programmation SAS à bas niveau. De l'ouverture chirurgicale de tables inconnues à l'envoi d'alertes e-mail personnalisées, nous avons vu que derrière l'apparente austérité des fonctions (OPEN, FETCH, FGET, FWRITE...), se cache en réalité le véritable moteur de l'automatisation SAS.
N'hésitez pas à intégrer progressivement ces fonctions dans vos macros utilitaires. Le code sera certes un peu plus long à écrire, mais la robustesse, la flexibilité et la sécurité que vous y gagnerez feront passer vos développements dans une toute autre dimension. Bonne programmation !






