Mails avec indy10 : contenttype/contentid/parentpart

Contenu du snippet

Mails avec Indy : contentType/ContentID/ParentPart

Note: Ce tuto n' est pas fait pour vous apprendre à envoyer un mail avec les compos Indy.
Il suppose que vous savez déjà comment faire, il vous permet simplement d' envoyer un mail de façon correcte selon les standards définis.
Comme vous pourrez le voir, c' est plus compliqué que ce que vous croyez ...

Problèmes rencontrés :
----------------------

- Envoi de mails dont le corps est en HTML et avec son alternatif en texte simple mais le receveur ne voit pas le mail en texte alternatif si son client de mail n' ouvre pas le corps en HTML ou alors celui-ci apparait comme anexe?!
- Les anexes ne sont pas visibles chez le receveur?!
- Je voudrais montrer des petites images dans mes mails en HTML mais ceux-ci apparaissent seulement en anexe chez le receveur?!
- etc ...

Source / Exemple :


Le problème est qu' il faut correctement définir: 
- la propriété ContentType du compo TIdMessage et de chaque objet (TIdText par exemple) inclu dans notre TIdMessage.
- la propriété ContentType/FileName/ContentID/ParentPart de l' objet TIdAttachmentFile. 
- la propriété ContentType/ParentPart de l' objet TIdText. 

Pour résoudre ce problème, j' ai crée le type suivant qui regroupe tous les cas de figure d' un mail: 
type
  TContentTypeMail = (cmPlainText_Html, cmHtml_Attach, cmHtml_RelatedAttach,
    cmPlainText_Html_Attach, cmPlainText_Html_RelatedAttach, cmPlainText_Html_Attach_RelatedAttach);

Explication de chaque élément du type : 
cmPlainText_Html = Envoi de mails dont le corps est en HTML et son alternatif en texte simple

cmHtml_Attach = Envoi de mails dont le corps est en HTML avec anexe(s) non lié(s) au corps en HTML

cmHtml_RelatedAttach = Envoi de mails dont le corps est en HTML avec anexe(s tous) lié(s) au corps en HTML

cmPlainText_Html_Attach = Envoi de mails dont le corps est en HTML et son alternatif en texte simple avec anexe(s) non lié(s) au corps en HTML

cmPlainText_Html_RelatedAttach = Envoi de mails dont le corps est en HTML et son alternatif en texte simple avec anexe(s tous) lié(s) au corps en HTML

cmPlainText_Html_Attach_RelatedAttach = Envoi de mails dont le corps est en HTML et son alternatif en texte simple avec anexe(s) lié(s) et autre(s) non lié(s) au corps HTML

Exemple d' utilisation: 
-----------------------

Désolé, mais faire un programme complet de démonstration ou "donner" le mien n' est pas possible. 
Je vais donc vous expliquer step by step comme on dit chez Billou (selon documents officiels de Indy, j' ai rien inventé)  !!!

Dans l' exemple plus bas, IdMsgSend est de type TIdMessage et IdSMTP1 est de type TIdSMTP. 

Pour les related Attachments (anexes qui vont être visualisés dans le corps en HTML): 
n' oubliez pas de définir la propriété ContentID de l' objet TIdAttachmentFile (le ContentID est celui qui vous avez mis dans le code HTML afin de visualiser l' anexe à l 'endroit désiré). 
Le ContentID peut être le nom du fichier ou tout autre chaine de caractères, l' important est qu'il ne doit pas y avoir 2 fois le même (Unique pour chaque anexe lié au corps HTML). 

Déclarez les variables suivantes: 
MailContent: TContentTypeMail; Permettra d' identifier le cas de figure de notre mail. 
MailRelatedAttach: Boolean;  permet de savoir avant l' envoi de mails si vous allez inclure des anexes liés au corps en HTML.  
MailAttach: Boolean;  permet de savoir avant l' envoi de mails si vous allez inclure des anexes non liés. 
HtmlPart: Integer; Indice de l' objet TIdText avec le corps en HTML, ça va permettre de lier un autre objet à cet TidText.  
PlainTextParentPart: Integer; // ParentPart que l' on va mettre pour l' objet contenant le corps en plain/text. 
HtmlParentPart: Integer; // ParentPart que l' on va mettre pour l' objet contenant le corps en HTML. 

ParentPart permet de savoir si un objet composant le mail (anexe ou texte) est lié à un autre objet du mail.  
ParentPart =-1 par défaut, ce qui veut dire que l' objet n' est pas lié à un autre objet. 

Pour comprendre, pensez par exemple qu' un TButton sur une TForm est lié à la form. 
La TForm a comme ParentPart -1, le TButton a comme ParentPart 0. 

Selon votre mail à envoyer, définissez les 2 variables suivantes :
MailRelatedAttach := true/false; // Mon mail possède des anexes liés au corps HTML.
MailAttach := true/false;  // Mon mail possède des anexes non liés. 
Notez que ces 2 variables peuvent être toutes les 2 à true, à false, ou une à true et l' autre à false. 

Grâce à ces 2 variables, on va pouvoir définir notre variable MailContent: 
if MailRelatedAttach or MailAttach
then begin
  if MailRelatedAttach and MailAttach
  then
    MailContent := cmPlainText_Html_Attach_RelatedAttach
  else
    if MailRelatedAttach
    then MailContent := cmPlainText_Html_RelatedAttach
    else MailContent := cmPlainText_Html_Attach;
end
else
  MailContent := cmPlainText_Html;

Ajout du/des Body et des anexes : 

Inicilialisez ces variables comme suit: 
  HtmlPart := -1;
  HtmlParentPart := -1;
  PlainTextParentPart := -1;

  if MailRelatedAttach and MailAttach
  then begin
    // C' est le cas le plus compliqué, on doit créer 2 objets vides un lié à l' autre:
    with TIdText.Create(IdMsgSend.MessageParts, Nil) do
    begin
      // Cet objet a le code 0 (part)
      ContentType := 'multipart/related; type="multipart/alternative"';
    end;

    with TIdText.Create(IdMsgSend.MessageParts, Nil) do
    begin
      ContentType := 'multipart/alternative';
      ParentPart  := 0;  // On lie cet objet à celui crée plus haut
    end;
          
    HtmlParentPart := 1;
    PlainTextParentPart := 1;
    HtmlPart := 0;
  end
  else
    if MailRelatedAttach or MailAttach
    then begin
      // On doit juste créer un TIDText en blanc et lier le corps en HTML e le corps en Plain-text à cet objet :
      with TIdText.Create(IdMsgSend.MessageParts, Nil) do
      begin
        ContentType := 'multipart/alternative';
      end;

      // Cet objet a le code 0 (part), donc on informe les variables pour faire la liaison plus tard:  
      HtmlParentPart := 0;
      PlainTextParentPart := 0;
    end;

  // Corp au format HTML :
  idTexto := TIdText.Create(IdMsgSend.MessageParts, Nil);
  idTexto.Body.Text := '<html> mon corps en HTML </html>';
  idTexto.ContentType := 'text/html';
  idTexto.ParentPart  := HtmlParentPart;

  // Corp au format Plain-Text :
  idTexto := TIdText.Create(IdMsgSend.MessageParts, Nil);
  idTexto.Body.Text := ' mon corps en plain/text';
  idTexto.ContentType := 'text/plain';
  idTexto.ParentPart  := PlainTextParentPart;

  // Pour chaque anexe : 
  TIdAttachmentFile.Create(IdMsgSend.MessageParts, PathFichier);
  Indiquez les propriétés suivantes suivant le type (Related ou non) : 
  
  Related: TIdAttachmentFile.ParentPart := HtmlPart; TIdAttachmentFile.FileName, TIdAttachmentFile.ContentID, 
  Non Related : TIdAttachmentFile.FileName;

  Si c' est une image (jpeg, bmp, gif), vous pouvez aussi définir la proprété ContentType: 
  TIdAttachmentFile.ContentType := 'image/jpeg';

Enfin, définissez le ContentType du mail grâce à la variable MailContent :
case MailContent of
  cmPlainText_Html                      : IdMsgSend.ContentType := 'multipart/alternative';
  cmHtml_Attach                         : IdMsgSend.ContentType := 'multipart/mixed';
  cmHtml_RelatedAttach                  : IdMsgSend.ContentType := 'multipart/related; type="text/html"'; // Não usamos este tipo porque mandamos sempre o mail em formato texto ...
  cmPlainText_Html_Attach               : IdMsgSend.ContentType := 'multipart/mixed';
  cmPlainText_Html_RelatedAttach        : IdMsgSend.ContentType := 'multipart/related; type="multipart/alternative"';
  cmPlainText_Html_Attach_RelatedAttach : IdMsgSend.ContentType := 'multipart/mixed';
end;

Voilà, vous pouvez envoyer le mail comme ça: 
IdSMTP1.Connect;

if IdSMTP1.Connected
then IdSMTP1.Send(IdMsgSend)

Je me suis pris la tête assez souvent, j' espère que ce sera utile à certains. 
A+

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.