Expédier des emails avec pièces jointes via Outlook

Comment expédier un email avec pièces jointes à partir d’Access ?

Le principe

Cet article complète l’article Expédier des emails via Outlook. Il reprend le même objet MailItem, en utilisant en plus sa propriété Attachments, qui permet d’ajouter des pièces jointes à un message. Les pièces jointes peuvent être en nombre quelconque, et de nature quelconque.

Le code Visual Basic

Recopiez le code ci-dessous dans un module standard d’Access :

Comment tester ?

La procédure SendOLMail2, ci-dessus, reçoit les pièces jointes (leur chemin en fait) dans un tableau. Elle doit donc être appelée à partir d’un autre bout de code VBA. Par exemple :

Une fois ce code tapé (et les chemins de fichiers corrigés), placez votre curseur quelque part entre le Sub et le End Sub, puis cliquez sur l’icône Exécuter Sub/UserForm. Bien sûr, vous pouvez modifier les dimensions du tableau astrFichiers, et ajouter d’autres pièces jointes si nécessaire.

Vous aimerez aussi...

22 réponses

  1. mamanhou dit :

    bonjour,

    Votre code marche s’il existe les pièces jointes mais s’il en manque une = c’est le bug fichier introuvable.
    Comment modifier votre code pour qu’il ne prenne que les PJ existantes ?

    merci pour votre aide
    Mamanhou

  2. Damien B dit :

    Bonjour tout le monde,

    J’ai lu avec intérêt pas mal de tutos sur ce site super bien fait (Merci à Hervé pour le boulot), mais je bloque sur un morceau de code que j’ai construit en fonction des tutos que j’ai lu.

    Fonction = envoi de mails spécifiques et personnalisés outlook à partir d’Access sur une sélection d’enregistrements (une requête s’en charge). J’arrive à bien faire ce que je veux sauf pour les pièces jointes. Je n’arrive pas à ajouter automatiquement les X pièces jointes dispo dans mon champ pièce jointe de ma table. Le recordset bloque à ce niveau.
    J’ai essayé un bout de code « For each PJ etc etc… » mais sans succès. Une idée?

    Code:
    Sub Outlook2_Click()
    Dim rst As DAO.Recordset
    Dim strMessageType As String
    Dim strTitre As String
    Dim strMsg As String
    Dim AQui As String
    Dim Fichier As String

    strTitre = « Echéance ATU {NomATU} pour {InitpatNOM}/{InitpatPRE} – Rappel »
    strMessageType = « Bonjour Docteur {Medecin}, » _
    & vbCrLf & vbCrLf _
    & « L’ATU n°{NumeroATU} de {NomATU} pour le patient {InitpatNOM}/{InitpatPRE} arrive à échéance le {EcheanceATU}.  » _
    & vbCrLf & vbCrLf & « Veuillez trouver ci-joint un formulaire à compléter et à nous retourner en cas de demande de renouvellement  » & vbCrLf _
    & vbCrLf & vbCrLf & « Merci de préciser la tolérance et l’efficacité du médicament » _
    & vbCrLf & vbCrLf & « Cordialement, » _

    ‘ Initialisation
    strSQL = « SELECT * FROM [RelanceMail] »
    Set rst = CurrentDb.OpenRecordset(strSQL, dbOpenSnapshot)
    With rst
    While Not rst.EOF
    ‘ Construire un message personnalisé
    strTitre = Replace(strTitre, « {NomATU} », rst(« NomATU »))
    strTitre = Replace(strTitre, « {InitpatNOM} », rst(« InitpatNOM »))
    strTitre = Replace(strTitre, « {InitpatPRE} », rst(« InitpatPRE »))
    strMsg = Replace(strMessageType, « {Medecin} », rst(« Medecin »))
    strMsg = Replace(strMsg, « {NomATU} », rst(« NomATU »))
    strMsg = Replace(strMsg, « {InitpatNOM} », rst(« InitpatNOM »))
    strMsg = Replace(strMsg, « {InitpatPRE} », rst(« InitpatPRE »))
    strMsg = Replace(strMsg, « {NumeroATU} », rst(« NumeroATU »))
    strMsg = Replace(strMsg, « {EcheanceATU} », rst(« EcheanceATU »))

    AQui = rst!Mail
    ‘ Fichier = rst!DocPUT (test par cette méthode mais ne fonctionne pas (DocPUT étant mon champ pièce jointe de ma requete/table)

    ‘commande l’envoie du mail
    Envoie_Message_dadou5821 strTitre, strMsg, AQui ‘, Fichier

    rst.MoveNext
    Wend
    End With
    ‘ Fermeture de la session Outlook et désallocation des objets
    rst.Close
    Set rst = Nothing

    End Sub

    Private Sub Envoie_Message_dadou5821(LeTitre As String, LeMessage As String, Destinataire As String, Optional ByVal avarFichiers As Variant)

    Dim MonOutlook As Object ‘New Outlook.Application
    Dim MonMessage As Object ‘Outlook.MailItem
    Dim varPJ As Variant
    Set MonOutlook = New Outlook.Application ‘avec reference outlook
    ‘Set MonOutlook = CreateObject(« Outlook.Application ») ‘sans reference outlook
    Set MonMessage = MonOutlook.CreateItem(olMailItem)
    ‘Remplissage de l’objet MailItem
    With MonMessage
    .To = Destinataire
    .Subject = LeTitre
    .Body = LeMessage
    .Attachments.Add « LOCALISATION FICHIER SYSTEMATIQUE »

    ‘ ici je souhaite ajouter les X pièces jointes de mon enregistrement selon l’enregistrement concerné mais fonctionne pas
    For Each varPJ In rst
    .Attachments.Add (varPJ)
    Next
    End With
    MonMessage.Display
    ‘ MonMessage.Send
    ‘ Fermeture de la session Outlook et désallocation des objets
    Set MonOutlook = Nothing
    End Sub

    • Hervé Inisan dit :

      J’ai peut-être raté quelque chose, mais j’ai l’impression que la variable rst n’existe pas la procédure Envoie_Message_dadou5821.
      Est-ce que ça peut être une piste ?

      • Damien B dit :

        En effet,

        rst étant mon recordset dans ma 1ère partie de code. Je l’ai déclaré dans la deuxième partie de code (envoi message dadou) mais rien n’y fait.
        je pense que ce n’est pas un argument valide

        • Hervé Inisan dit :

          Il faut non seulement que rst soit déclaré, mais aussi qu’il ait une valeur (la variable doit pointer un objet Recordset valide).
          Sinon, que contient rst, et comment sont stockées les pièces jointes ?

  3. Salut Hervé,
    Tout d’abord merci pour ce site qui à été et reste une mine d’or inépuisable d’informations précieuses pour moi et bien d’autres 🙂

    Je te solicite car j’ai un petit problème similaire à « Greed » d’Erreur -115396542 Ce chemin d’accès n’existe pas. Assurez vous qu’il est correct.” avec ce code et je ne trouve pas de solution :

    Sub EnvoiMail_click()
    ‘ Initialisation :
    Dim astrFichiers(1 To 3) As String
    Dim strDest As String ‘ L’adresse e-mail du destinataire envoyée
    Dim strMessage As String ‘ Le corps du message
    Dim ListeEMail As Recordset ‘ Variable reçevant l’E-Mail de la liste
    Set ListeEMail = CurrentDb.OpenRecordset(« R_EMailOUI ») ‘Requête contenant les E-Mails sélectionnés
    Dim Message As String ‘ Message à Saisir
    ListeEMail.MoveFirst ‘Positionnement au début de la liste

    ‘ Création du message
    strObj = « Message de votre club préféré » ‘ Objet du Message
    Message = InputBox(« Saisissez votre Message : », « Message à envoyer ») ‘Saisie du Message
    astrFichiers(1) = InputBox(« Saisissez le lien vers la 1ère Pièce à joindre : », « Fichier à envoyer ») ‘Saisie de la P.J.
    astrFichiers(2) = InputBox(« Saisissez le lien vers la 2ème Pièce à joindre : », « Fichier à envoyer ») ‘Saisie de la P.J.
    astrFichiers(3) = InputBox(« Saisissez le lien vers la 3ème Pièce à joindre : », « Fichier à envoyer ») ‘Saisie de la P.J.

    ‘Corps du Message
    strMessage = strMessage & vbCrLf & « Bonjour, »
    strMessage = strMessage & vbCrLf & vbCrLf
    strMessage = strMessage & Message
    strMessage = strMessage & vbCrLf & vbCrLf
    strMessage = strMessage & vbCrLf & « Cordialement,  »
    strMessage = strMessage & vbCrLf
    strMessage = strMessage & vbCrLf & « Monsieur X »

    ‘ Création de la liste selon sélection :
    While Not ListeEMail.EOF
    strDest = ListeEMail(« E-Mail »)
    SendOLMail strDest, strObj, strMessage, False, astrFichiers
    ListeEMail.MoveNext
    Wend

    ‘ Clôture des Fonctions !
    MsgBox « Envoi du (des) mail(s) Terminé ! », vbInformation, « Information »
    ListeEMail.Close
    Set ListeEMail = Nothing
    End Sub

    le sendOLMail étant celui posté plus haut.

    Pourrais-tu me sortir de ce mauvais pas ? 🙂 Merci d’avance de ton temps consacré 😉

    • Hervé Inisan dit :

      Je vois que les chemins sont demandés manuellement par MsgBox. Ça peut augmenter le risque d’erreur de saisie, donc de chemin incorrect. Il y a aurait au moins 2 façons de gérer ça :

      1. Soit faire des Dir() pour vérifier que les fichiers existent bien.
      2. Soit (mieux) uiliser un FileDialog pour permettre à l’utilisateur de sélectionner le fichier sans taper son chemin. Tu as des exemples de FileDialog sur le site.

      D’autre part, ton code attend systématiquement 3 fichiers, ce qui ne sera sans doute pas le cas tout le temps (il faudrait du coup adapter pour pouvoir gérer de 0 à n fichiers).

  4. Hervé Inisan dit :

    tadresse > Le premier bout de code – SendOLMail2 – doit être placé dans un module standard, mais il n’est pas prévu pour être associé directement à un bouton (ça permet de le réutiliser pour plusieurs boutons).

    Par contre, tout ce qui est dans le bloc TestSendOLMail2peut faire l’objet d’un bouton, effectivement. C’est ce bloc qui déclenche l’appel de la procédure générique donnée au début.

  5. tadresse dit :

    Bonjour je voudrais savoir si je peu placer ce code sur l’évènement click d’un boutton parce que j’essaye de puis et ca donne pas

    Merci d’avance

  6. Hervé Inisan dit :

    biloux > Dans cet article-ci, tu as la procédure pour envoyer un fichier (quelconque) avec Access, du moment que tu connais son chemin. Regarde les articles qui parlent de la création de documents PDF, tu auras l’autre partie. Ce que tu souhaites, c’est enchaîner les deux :

    1. Produire un PDF.
    2. L’envoyer par Outlook.
  7. biloux dit :

    bjr,
    je souhaite envoyer un page d’un etat (access) via outlook. comment demander à outlook de recuperer un aperçu avant impression, de le convertir sous PDF avant de récupérer le chemin pour l’envoi;
    Merci

  8. Hervé Inisan dit :

    Greed > Content que ça marche. 🙂

    Bon dév’ !

  9. Greed dit :

    C’est bon ça fonctionne, c’était bien au niveau de la déclaration du tableau que ça déconnait ^^

    Merci beaucoup pour ces réponses claires et précises, très bon site au passage et si j’ai d’autres questions j’hésiterai pas :p

    A la revoyure !

  10. Hervé Inisan dit :

    Greed > Le problème vient sans doute du Dim astrFichiers(1). En VBA, si on ne met qu’un seul chiffre entre les parenthèses, ce chiffre est l’indice maximal du tableau, le tableau démarrant implicitement à 0. Ce qui veut dire que, dans ton cas, astrFichiers(0) est vide, et astrFichiers(1) contient un chemin. D’où sans doute le problème dans la boucle, le premier fichier étant introuvable.

    Pour éviter les ambiguïtés, remplace Dim astrFichiers(1) par Dim astrFichiers(1 to 1). Dans ce cas, on précise explicitement l’indice de départ et l’indice d’arrivée.

    Pour ce qui est du For Each : je le garderais dans SendOLMail2(), parce que ce bloc de code est une « boîte noire », il n’a pas besoin d’être retouché. Sinon, le jour où tu as 2 pièces jointes (ça peut arriver, donc ça arrivera ;-)), on doit remodifier…

  11. Greed dit :

    J’ai bien changé le chemin, mais j’ai fait une petite modif du coup, étant donné que je n’ai qu’un seul fichier à envoyer(fichier word).

    J’ai mis : Dim astrFichiers(1) (au lieu de 1 to 3 mais à mon avis c’est pas ça le problème)

    le chemin est assez long et commence par V: (mais comme j’ai fait un copié collé du chemin dans l’explorateur,avec la pièce jointe ensuite, il devrai pas y avoir de soucis)

    A moins qu’il y ai un problème au niveau du ForEach ?
    J’y pense à l’instant mais comme il n’y a qu’une seul pièce jointe peut-être qu’il n’y aurai pas besoin de ForEach ?

  12. Hervé Inisan dit :

    Greed > Comme dit dans l’article, tu as corrigé les chemins ? (pas de C:… mais quelque chose de réel)

    Si ça peut aider, tu peux poster le chemin ici.

  13. Greed dit :

    Bonjour, j’ai un problème avec cette procédure.

    En fait, lorsque j’exécute le code, je reçois un message d’erreur de ce type : »Erreur -115396542 Ce chemin d’accès n’existe pas. Assurez vous qu’il est correct. »

    J’ai bien vérifié plusieurs fois le chemin mais rien n’y fait, je ne comprend pas.

    Si vous pouviez résoudre mon problème ce serai bien sympa.

    Cordialement

    Greed.

  14. Hervé Inisan dit :

    ZZDriver > Un peu tard pour la réponse… mais à vue de nez, c’est bien tout ça qu’il faut faire pour aménager le code !

  15. ZZdriver dit :

    Merci beaucoup pour la réponse, cela m’apprendra à lire correctement, j’ai confondu la référence  » Microsoft Outlook 12.00″ et « Microsoft office 12.0 »

    J’imagine que si je souhaite envoyer l’email en copie,
    je dois ajouter sous la ligne :
    « ByVal strEmail As String, _ »

    la ligne :
    « ByVal strEmailCC As String, _ »

    Et sous la ligne:
    « .To = strEmail »

    la ligne :
    « .CC= strEmailCC »

    Et pour finir compléter la ligne dans le Sub:
    « SendOLMail2 [email], _ »

    avec:
    « SendOLMail2 [email],[emailCC], _

    [emailCC] étant le nom du champ qui contient, dans mon formulaire, l’adresse email à mettre en copie.

    Si vous avez le temps de me le confirmer, je vous en remercie d’avance.

    Excellent week-end.

    ZZ

  16. Hervé Inisan dit :

    zzdriver > Il s’agit d’un problème de références. Le haut de cet article donne un lien vers un article précédent (Expédier des mails via Outlook) où la réponse est donnée. Bons tests !

  17. zzdriver dit :

    Bonjour, je ne suis peut être pas très doué mais lorsque je test, j’ai un avertissement  » Type défini par l’utilisateur non défini »

    Les lignes suivantes sont surlignées en jaune :
    Public Sub SendOLMail2( _
    ByVal strEmail As String, _
    ByVal strObj As String, _
    ByVal strMsg As String, _
    ByVal blnEdit As Boolean, _
    Optional ByVal avarFichiers As Variant)

    ET cette ligne est surlignée en bleu :
    Dim ol As Outlook.Application

    Mon logiciel de messagerie est bien Outlook.

    Si vous aviez une idée, cela me rendrait bien service.

    Cordialement,

    ZZdriver

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *