Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erschien. - Albert Einstein
emde IT-LÖSUNGEN
> Tel. 08131 / 99 69 80-0
> Kontakt per E-Mail
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).


Kommentare (2)
Leonardo
am 09.06.2019Nach langer Entwicklungszeit möchten wir unsere VBA-Entwicklung schützen. Leider liest man an vielen Ecken, wie man Passwörter knacken kann. Schutz und Urheberrechte scheinen nicht "in" zu sein. Deshalb vielen Dank für Deine/ tolle Doku. Funktioniert tadellos mit Gmail.
Allerdings werden wir weitere Schutzmechanismen einbauen müssen, leider wissen wir noch nicht wie wir das am Besten tun.
Eine Status-mail mit der Lizensnummer ist schon mal der erste Schritt, Danke!!
Euch viel Erfolg
Leonardo
Wolfgang
am 28.09.2025Allerdings: es ist ein Fehler darin:
Wenn ein Provider tatsächlich TLS fordert, dann funktioniert es nicht mit Port 587
Habe A1 Business-Zugang. Im Outlook ist zwar Port 587 eingestellt, aber bei dieser Funktion kam immer Fehler: "Der Server hat die Absenderadresse Zurück gewiesen ......Must issue a StartTLS command first.
Sendtls funktioniert nur mit Port 25 !!
Genauer beschrieben und dokumentiert hier:
https://codekabinett.com/rdumps.php?Lang=2&targetDoc=cdo-starttls-smtpusessl
Anna
am 30.09.2025Deine Anmerkung zeigt aber, dass es Abweichungen von der Norm geben kann und man das mit dem Provider klären muss, wenn es nicht auf Anhieb klappt.