Les fichiers msg sont du CFBF et Apache POI dispose justement d'une API pour lire/créer des fichiers de ce type. En creusant un peu, il n'y a que deux librairies propriétaires capable de créer des fichiers msg. Bien que capable de les lire, Apache POI ne permet pas d'en écrire, j'ai donc décidé de remédier à cela.

Comme Microsoft met a disposition la spécification d'un fichier msg, il est assez simple de créer un fichier compréhensible par Outlook. Sauf que, quand il y a une erreur, Outlook se borne a dire que le fichier n'est pas valable. Et à ce moment, il ne reste plus qu'à comparer (en binaire) un fichier généré par mon code et un autre valide.

La structure interne étant connue, j'ai utilisé CFX afin de voir les noeuds qui m'intéressaient. En l'occurrence, la spécification le donne précisément, il s'agit de __properties_version1.0. Et c'est là que vim rentre en scène: une fois le fichier ouvert, la commande :%!xxd permet d'afficher le contenu du fichier en hexadécimal, que l'on peut éditer avec toute la puissance de vim !

00000000: 0000 0000 0000 0000 0300 0000 0000 0000  ................
00000010: 0300 0000 0000 0000 0000 0000 0000 0000  ................
00000020: 4000 0730 0200 0000 70d7 72d8 4d64 d201  @..0....p.r.Md..
00000030: 4000 0830 0200 0000 70d7 72d8 4d64 d201  @..0....p.r.Md..
00000040: 0300 f70f 0200 0000 0000 0000 7000 4400  ............p.D.
00000050: 0300 f40f 0200 0000 0200 0000 6300 6100  ............c.a.
00000060: 0300 0d34 0200 0000 790e 0400 6f00 7300  ...4....y...o.s.
00000070: 1f00 040e 0200 0000 1a00 0000 0300 fd75  ...............u
00000080: 1f00 030e 0200 0000 1a00 0000 0300 0000  ................
00000090: 1f00 020e 0200 0000 1c00 0000 0300 440d  ..............D.
000000a0: 0a                                       .

La 1ère colonne indique les lignes. Les 8 premiers bytes sont tous des zéros, tels que décrits dans la spécification. Vient ensuite une autre série de 8 byte pour la définition du header. Enfin la dernière colonne représente le contenu de la ligne (ce qui n'a pas d'importance dans ce cas).

Généralement, les 8 premiers bytes sont constitués d'un tag, qui est une composition binaire du type de variable ainsi que son id. Par exemple, la variable PidTagStoreSupportMask a l'identifiant 0x340D et est de type Integer (0x0003). On peut la voir à la ligne 00000060. Les valeurs sont stockées en LittleEndian.

Afin de comprendre ce qui n'allait pas, j'ai donc modifié le contenu pour supprimer une à une les variables en trop. Une fois la modification faite, il faut faire :%!xxd -r pour reconvertir l'hexadécimal en binaire, puis le réintégrer dans le "msg" avec CFX. Et j'ai pu ainsi voir quelles étaient les variables minimum nécessaires !

A noter que je triche un peu: xxd ne fait pas partie de vim à proprement parler, c'est un programme à part entière qui est simplement appelé au travers de vim.