E-Mails versenden mit CDO

15. Mai 2013 / Letzte Aktualisierung: 03. Februar 2020

Für den Versand von E-Mails per VBA bieten sich auf den ersten Blick zwei Möglichkeiten an:

  • DoCmd.SendObject
  • Generieren und Versenden der E-Mail per Outlook

Gegen diese Möglichkeiten sprechen folgende Argumente:

  • Bei Anwendung der SendObject-Methode ist es für den Entwickler hinderlich, dass der Benutzer eine Warnmeldung erhält und dem Versand explizit zustimmen muss. Verweigert er die Zustimmung, wird die E-Mail nicht versendet. Diese Methode eignet sich deshalb z.B. nicht, um den Datenbank-Entwickler - vom Benutzer unbemerkt - über ein Problem zu informieren.
  • Das Versenden einer E-Mail per Outlook funktioniert inzwischen ohne Interaktion mit dem Benutzer, allerdings setzt es voraus, dass Outlook bzw. Exchange Server in der aktuellen Umgebung installiert und eingerichtet ist, was z.B. auf einem Terminalserver nicht unbedingt der Fall ist. Außerdem erscheinen die versendeten E-Mails im Postfach desjenigen, dessen Account verwendet wurde.

E-Mails mit CDO

Eine elegante Lösung für den automatischen Versand von Emails ohne Outlook bieten die Microsoft Collaboration Data Objects (CDO). Eine einfache E-Mail im Nur-Text-Format kann über einen lokalen SMTP-Server z.B. folgendermaßen versendet werden:

Public Function EmailVersand()

Dim OutMail As Object
Dim Schema As String

Const cdoSendUsingPort = 2 ' send the message using the network (SMTP over the network)
Const cdoAnonymous = 0     ' do not authenticate

  Set OutMail = CreateObject("CDO.Message")
  Schema = "http://schemas.microsoft.com/cdo/configuration/"

  With OutMail
    .From = <EmailAbsender>
    .To = <EmailEmpfänger>
    .Subject = <Betreff>
    .BodyPart.Charset = "iso-8859-1"
    .TextBody = "Guten Tag, dies ist ein Test."
    With .Configuration.Fields
      .Item(Schema & "sendusing") = cdoSendUsingPort
      .Item(Schema & "smtpserver") = <Server>
      .Item(Schema & "smtpserverport") = 25
      .Item(Schema & "smtpauthenticate") = cdoAnonymous
      .Update
    End With
    .Send
  End With

  Set OutMail = Nothing
  
  Exit Function

End Function

Wird ein externer SMTP-Server verwendet, so muss man noch die Authentifizierung ergänzen:

Const cdoBasic = 1  ' use basic (clear-text) authentication

      ...
      .Item(Schema & "smtpauthenticate") = cdoBasic
      .Item(Schema & "sendusername") = <EmailAccount>
      .Item(Schema & "sendpassword") = <Password>
      ...

Wird eine SSL-Verbindung bzw. TLS (Transport Layer Security) verwendet, so wird dies über den Parameter smtpusessl bzw. sendtls mitgeteilt:

.Item(Schema & "smtpusessl") = 1
.Item(Schema & "sendtls") = 1

Eigentlich ist TLS die neue Bezeichnung für SSL (Secure Sockets Layer), deshalb ist es m.E. verwunderlich, dass es hierfür zwei Parameter gibt. Auf jeden Fall muss man, wenn eine Verschlüsselung verwendet wird, berücksichtigen, dass dann der Port angepasst werden muss: Port 465 für SSL, Port 587 für TLS.

Man kann auch leicht eine E-Mail mit HTML-Formatierung erstellen, indem man anstelle von .TextBody die Eigenschaft .HTMLBody verwendet:

    .HTMLBody = <html><p>Guten Tag, dies ist ein Test.</p></html>"

Über die Eigenschaft .AddAttachment kann man Dateien als Anhang hinzufügen:

    .AddAttachment = <Datei1>
    .AddAttachment = <Datei2>

Möchte man in einer E-Mail im HTML-Format ein Bild anzeigen, so muss man dieses als eingebettetes Content-Element hinzufügen und kann es dann unter der vereinbarten ID im Body der E-Mail verwenden:

Dim BP As Object

Const CdoReferenceTypeName = 1

...

 Set BP = OutMail.AddRelatedBodyPart("<Grafikdatei>",  _
         "pic1.jpg", CdoReferenceTypeName)
 BP.Fields.Item("urn:schemas:mailheader:Content-ID") = _
         "<pic1.jpg>"
 BP.Fields.Update

  ...

    .HTMLBody = "<html><img src="cid:pic1.jpg" /></html>"

Infos zu allen Parametern zur Konfiguration von CDO findet man im
» Microsoft Developer Network.

Konfiguration des SMTP-Servers

Bei manchen SMTP-Servern müssen noch Einstellungen vorgenommen werden, damit es mit dem Versand von E-Mails klappt bzw. manchmal muss man mit gewissen Einschränkungen leben.

  • Gibt es einen Exchange-Server, den man selbst konfigurieren kann, so muss - sofern man dieses Feature verwenden möchte - in der Postfachstellvertretung hinterlegt werden, dass der Absender und der SMTP-User nicht identisch sein müssen.
  • Bei der Verwendung von smtp.gmail.com müssen Absender und Konto-Inhaber identisch sein, d.h. hier machen wir es z.B. so, dass in jeder Session beim ersten Versand einer E-Mail das Google-Passwort des Benutzers erfragt wird. Außerdem muss im Google-Account angegeben werden, dass die Datenbank auf Gmail zugreifen darf (Zugriff durch unsichere Apps erlauben).