Language: Deutsch English















Last Update: 2021 - 07 - 08





Emails aus Access mit VBA und CDO versenden

von Philipp Stiefel, ursprünglich veröffentlicht 15. November 2015

zuletzt aktualisiert 2021-07-09


retro typewriter, article header image

Die zwei anderen Ansätze um Emails aus Microsoft Access zu versenden haben beiden ihre Stärken und Schwächen.

Emails mit der DoCmd.SendObject Anweisung zu versenden ist sehr einfach und unabhängig von dem installierten Email-Client, es hat aber auch nur eine sehr begrenzte Funktionalität.

Outlook Automation für den Email-Versand zu verwenden ist dagegen sehr mächtig und es gibt nur wenig, was man damit nicht erreichen kann. Allerdings ist dieser Ansatz komplett davon abhängig, dass auch Microsoft Outlook auf dem Rechner installiert ist, auf dem deine Access Anwendung läuft. Darüber hinaus wird der Ansatz dadurch behindert, dass Microsoft immer mehr Sicherheitsmaßnahmen implementiert um den Zugriff von anderen Anwendungen auf Outlook zu kontrollieren und einzuschränken.

Darf ich vorstellen, die CDO Bibliothek

Hier möchte ich Dir jetzt eine weitere Methode vorstellen, um Emails über Visual Basic Code aus deiner Access Anwendung zu senden. Diese Methode basiert auf den Collaboration Data Objects (CDO). Die vollständige Bezeichnung der Bibliothek, die wir nutzen werden, ist Microsoft CDO for Windows 2000. Diese Bibliothek ist nicht abhängig von dem installierten Email-Client, denn die komplette Funktionalität um Emails zu versenden ist bereits in ihr integriert.

Ein großer Vorteil dieser Bibliothek ist, dass du davon ausgehen kannst, dass sie bereits auf dem Rechner, auf dem deine Anwendung laufen wird, installiert ist. Sie ist in der Betriebssysteminstallation von Windows NT enthalten, seitdem Microsoft Windows 2000 veröffentlicht wurde. Dies ist zwar keine Garantie für die Zukunft, aber im Moment brauchen wir uns keine Gedanken darüber machen, ob diese Bibliothek vielleicht nicht vorhanden sein könnte.

Eine einfache Email versenden

Ok, ich zeige Dir jetzt, wie du eine einfache Email mit CDO versenden kannst.

Bevor wir loslegen können, musst Du einen Verweis auf die CDO-Bibliothek setzen. Dazu rufe das Menü Extras->Verweise im VBA-Editor auf. Wenn du die Bibliothek nicht in der Liste der Verweise findest, kannst du einfach über den Datei-Dialog danach suchen. Füge die Bibliothek cdosys.dll aus dem Windows System32 (SysWow64 auf 64-bit Systemen) hinzu.

Screenshot der VBA Verweise mit der hinzugefügten CDO Bibliothek

Wenn du die CDO-Bibliothek nicht zu den Verweisen in deinem Projekt hinzufügen möchtest, kannst du auch Late Binding verwenden. Um dies zu einfacher zu machen, habe ich ein Modul mit allen Enums und Konstanten aus der CDO-Bibliothek zum Download erstellt.

Nachdem du entweder die Bibliotheksreferenz oder das VBA-Modul mit den Konstanten in deinem Projekt ergänzt hast, kannst du diese Prozedur in einem neuen Modul in der VBA-Entwicklungsumgebung einfügen.

Public Sub SendSimpleCDOMail() Dim mail As CDO.MESSAGE Dim config As CDO.Configuration Set mail = CreateObject("CDO.Message") Set config = CreateObject("CDO.Configuration") config.Fields(cdoSendUsingMethod).Value = cdoSendUsingPort config.Fields(cdoSMTPServer).Value = "mail.mycompany.invalid" config.Fields(cdoSMTPServerPort).Value = 25 config.Fields.Update Set mail.Configuration = config With mail .To = "someone@somewhere.invalid" .From = "me@mycompany.invalid" .Subject = "First email with CDO" .TextBody = "This is the body of the first plain text email with CDO." .AddAttachment "C:\path\to\a\file.dat" .Send End With Set config = Nothing Set mail = Nothing End Sub

Als nächstes solltest du natürlich die Werte für den Mail Server Namen, die Email-Adressen und den Pfad zu dem Dateianhang mit Werten ersetzen, die in deiner Umgebung gültig sind. Wenn du im Moment noch keinen Dateianhang mitsenden willst, kannst du diese Zeile einfach auskommentieren.

Während du das tust, fällt dir vielleicht schon ein kleines Problem mit diesem Ansatz auf. – Du musst den Namen des Mail Servers wissen, den später die Benutzer der Anwendung verwenden werden.

Jetzt, nachdem du die Werte angepasst hast, führe den Code aus um eine Email zu versenden. – Funktioniert es?

Du solltest nicht zu sehr überrascht sein, wenn beim Aufruf der Send-Methode ein Laufzeitfehler auftritt und eine Fehlermeldung ähnlich dieser Auftritt.

Screenshot der Fehlermeldung '530 Authentication required'
The server rejected the sender address. The server response was: 530 Authentication required

Dies bedeutet, dass dein Mail Server die Email abgewiesen hat, die wir gerade versenden wollten. Dies ist eigentlich eine gute Sache, denn es zeigt, dass der Mailserver Spam verhindert und nicht zulässt, dass einfach irgendjemand eine Email versendet.

Authentifizierung

Um uns beim Mail Server zu authentifizieren müssen wir unser Zugangsdaten übermitteln. Um das zu tun, fügen wir einfach diese drei Zeilen mit dem Benutzernamen und Kennwort zu den Konfigurationseinstellungen in Code hinzu.

config.Fields(cdoSMTPAuthenticate).Value = cdoBasic config.Fields(cdoSendUserName).Value = "youUserName" config.Fields(cdoSendPassword).Value = "yourPassword"

Versuch jetzt noch einmal die Email mit durch Ausführen des VBA-Codes zu senden. – Jetzt sollte es funktionieren.

Nimm zur Kenntnis, dass dies zwei weitere Werte sind, die du in den Konfigurationseinstellungen deiner Access Anwendung speichern musst, oder du kannst sie jedes Mal vom Benutzer eingeben lassen, wenn er eine Email senden möchte (unschön).

Wenn deine Anwendung innerhalb einer Windows Domäne mit Active Directory verwendet wird und der Benutzer in der Domäne angemeldet ist, kannst du auch NTLM Authentifizierung verwenden. Der Benutzer (oder die Anwendung) müssen dann Benutzername und Kennwort nicht mehr an den Mailserver übergeben.

Um dies zu aktivieren, ändere die Konfigurationseinstellung für cdoSMTPAuthenticate zu cdoNTLM.

config.Fields(cdoSMTPAuthenticate).Value = cdoNTLM

Natürlich muss NTLM Authentifizierung auf dem Mailserver aktiviert sein, damit dies funktionieren kann.

Verschlüsselung

Jetzt sind wir eigentlich fertig, aber wir können die Sicherheit unserer Implementierung noch weiter verbessern. Die meisten Email-Server unterstützen auch verschlüsselte Verbindungen für den Email Versand. Die CDO-Bibliothek kann das auch.

Um SSL Verschlüsselung für den Email-Versand zu aktivieren füge diese eine Zeile zum Code hinzu und ändere den Wert für cdoSMTPServerPort.

config.Fields(cdoSMTPServerPort).Value = 465 config.Fields(cdoSMTPUseSSL).Value = True

Außerdem ändere die Portnummer in der Zuweisung der Konfiguration auf 465. Probiere aus, ob der Email-Versand noch funktioniert.

Es gibt einige Situation in denen es nicht funktionieren wird, die Email über eine verschlüsselte Verbindung zu versenden. Das SSL-Zertifikat des Servers könnte auf dem Client als nicht vertrauenswürdig eingestuft werden. Dann kann sich die CDO-Bibliothek nicht zum Server verbinden. Manche Mailserver unterstützen auch keine implizite SSL-Verbindung auf Port 465, sondern nur explizite TLS-Verbindungen über Port 587. Dies wird unglücklicherweise nicht von der CDO-Bibliothek unterstützt.

Opportunistische TLS-Verschlüsselung mit STARTTLS

Manche Mailserver erwarten eine opportunistische TLS-Verschlüsselung. Eine solche Verbindung wird zuerst als unverschlüsselte Verbindung, üblicherweise auf Port 587, aufgebaut. In der Aushandlungsphase der Verbindung zwischen Client und Server, zeigt der Server an, dass er eine Verschlüsselung über TLS (Transport Layer Security) unterstützt. Der Client sollte dann mit dem STARTTLS Befehl die Verschlüsselung der Verbindung mit TLS einleiten.

Es gibt zahlreiche Code-Beispiele im Internet, die behaupten es gäbe eine undokumentierte sendtls Konfigurationseinstellung, die eine CDO-Verbindung dazu bringt, den STARTTLS Befehl zu senden und somit eine bestehende Plain-Text Verbindung zu einer TLS-verschlüsselten Verbindung auszubauen. – Sogar ich habe das für eine Zeit lang hier verbreitet, wie folgt:

config.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendtls").Value = True

Das funktioniert nicht! Die sendtls Konfigurationseinstellung existiert nicht in der CDOSYS.dll! Die CDO-Bibliothek unterstützt keine opportunistische Verschlüsselung mit STARTTLS.

Ich vermute, dieses Gerücht wurde durch die Tatsache begünstigt, dass viele Mailserver STARTTLS optional unterstützen, aber nicht zwingend darauf bestehen. In diesem Fall kannst du Emails mit sendtls=true versenden, aber es bewirkt absolut gar nichts und deine Verbindung wird überhaupt nicht verschlüsselt. Wenn STARTTLS vom Server vorausgesetzt wird, wirst du eine Fehlermeldung wie die folgende sehen:

The server rejected the sender address. The server response was: 451 5.7.3 STARTTLS is required to send mail.

Wenn dein Emailprovider empfiehlt sich zum Mailserver auf Port 587 mit STARTTLS zu verbinden, dann empfehle ich, dass du alternativ ausprobierst dich auf Port 25 oder Port 465 mit smtpusessl=true zu verbinden. Auch wenn das oft nicht dokumentiert ist, funktioniert es bei vielen Providern, einschließlich Microsoft/Office 365 (smtp.office365.com) trotzdem. (Unten gibt es noch mehr Informationen zu Office 365.)

Wie wichtig ist Verschlüsselung?

Wie wichtig die Verschlüsselung der Verbindung ist, hängt von der Umgebung ab, in dem deine Anwendung eingesetzt wird. Wenn sich der Mailserver innerhalb eines lokalen Firmennetzwerkes befindet, würde ich trotzdem empfehlen die Verbindung zu verschlüsseln, auch wenn zur Not darauf verzichten kann. Falls aber der Server irgendwo im Internet gehostet wird, ist Verschlüsselung zwingend erforderlich.

E-Mails mit CDO über Microsoft/Office 365 senden

CDO kann E-Mails über Microsoft 365 (ehemals Office 365) unter Verwendung des Mailservers smtp.office365.com auf Port 25 mit der Option smtpusessl=true senden. – Es gibt jedoch einige Fallstricke, die dies erschweren oder unmöglich machen können.

CDO authentifiziert dein Benutzerkonto beim Mailserver mithilfe des SMTP AUTH-Protokolls. Abhängig von den Sicherheitsrichtlinien deiner Organisation muss SMTP AUTH für Exchange Online aktiviert werden, bevor du E-Mails mit CDO senden kannst. – Ich glaube nicht, dass es möglich ist, CDO mit moderner OAuth-Authentifizierung zu verwenden. Selbst wenn dies der Fall wäre, wäre zusätzlicher Code erforderlich, um den OAuth-Prozess zu implementieren, bevor du überhaupt mit der Verwendung von CDO beginnen kannst.

Normalerweise wird die Basic Authentication (Benutzername + Passwort) verwendet, um sich bei Mailservern außerhalb des lokalen Netzwerks zu authentifizieren. Dies kann mit Office 365 funktionieren. Ihre Organisationsadministratoren haben jedoch möglicherweise die Basic Authentication für Exchange Online deaktiviert. Dann muss du Sie sie dazu bringen, eine Ausnahme für das Postfach zu konfigurieren, das du mit CDO verwenden möchtest. Wenn deine Benutzer bei Azure-AD authentifiziert sind, könntest du versuchen, ob die in CDO verfügbare NTLM-Authentifizierungsoption deine Anforderungen genügt. (Ich hatte nicht die Zeit, das in der Praxis auszuprobieren.)

Wenn du nur E-Mails an Empfänger innerhalb deiner Office-365-Organisation senden möchtest, kannst du auch den Ansatz Direct Send (Option 2) für Drucker und ähnliche Geräte ausprobieren.

E-Mail mit CDO über Googlemail/GMail senden

Wenn du versuchst, ein Googlemail-/GMail-Konto zum Senden von E-Mails mit CDO zu verwenden, wirst du sehr wahrscheinlich auf ein Problem stoßen.

Der Code in VBA zum Senden einer E-Mail über Googlemail/GMail ist der gleiche wie bei jedem anderen E-Mail-Anbieter. Es gibt jedoch ein wichtiges Detail, das du berücksichtigen musst. Die direkte SMTP-Authentifizierung ist für Gmail standardmäßig deaktiviert. Du musst in deinen Google-Kontoeinstellungen explizit Less secure Apps aktivieren. Nachdem du dies getan hast, kannst du dich wie gewohnt mit deinem Benutzernamen und Passwort authentifizieren, um E-Mails mit CDO zu senden.

Wenn du 2-Faktor-Authentifizierung für dein Google-Konto verwendest, kannst du Less secure Apps nicht aktivieren. Dann musst du ein spezielles App-Passwort für Gmail erstellen. Nachdem du das App-Passwort generiert hast, verwendest du es im VBA/CDO-Code anstelle deines normalen Passworts, um dich beim SMTP-Server zu authentifizieren.

Häufige Probleme und Fehler Diagnostizieren

Wenn du versuchst, eine E-Mail zu senden aber dies mit einem Fehler fehlschlägt, lautet die VBA-Fehlernummer normalerweise -2147220975 (0x80040211 = CDO_E_SMTP_SEND_FAILED). Dies ist nicht besonders hilfreich, da das Senden der E-Mail aus verschiedenen Gründen fehlgeschlagen sein kann.

Screenshot einer CDO Anmeldefehler-Meldung: '-2147220975 The message could be sent to the SMPT server. The transport error code was 0x80040217.'

Anstatt dich auf die unmittelbare Fehlernummer zu konzentrieren, schau dir den Transport Error Code im Text der Nachricht genau an. Wenn du dort siehst …

… 0x80040217 (=CDO_E_LOGON_FAILURE) oder 0x80040215 (=CDO_E_AUTHENTICATION_FAILURE) weist die Fehlermeldung auf ein Problem mit der Authentifizierung hin. Wenn du genau überprüft hast, dass du den richtigen Benutzernamen und das richtige Kennwort verwendest aber dieser Fehler weiterhin auftritt, liegt der Grund wahrscheinlich daran, dass die SMTP-Authentifizierung mit Benutzernamen und Kennwort für das Konto, das du verwenden möchtest, nicht aktiviert ist. Für Microsoft 365 und Gmail habe ich oben mögliche Ursachen und Lösungen erläutert. Bei anderen Mailanbietern lies deren Dokumentation oder wende dich an den Support.

… 0x80040213 (=CDO_E_FAILED_TO_CONNECT) die Ursache ist entweder, dass du versuchst, eine Verbindung zu einem Server oder Port herzustellen, der keine Verbindungen akzeptiert, oder dass du eine Verbindung zu einem Server/Port herstellst, der nur unverschlüsselte Verbindungen unterstützt, während du die smtpusessl-Option in der CDO-Konfiguration aktiviert hast. Der Fehler kann vermutlich auch auftreten, wenn der Server ein nicht vertrauenswürdiges Zertifikat für die SSL/TLS-Verschlüsselung verwendet, aber das sollte bei seriösen Mailanbietern nicht passieren.

… 0x80040212 (=CDO_E_CONNECTION_DROPPED) die Ursache ist wahrscheinlich, dass du die SSL/TLS-Verschlüsselung in der CDO-Konfiguration nicht aktiviert hast, der Server jedoch zwingend eine verschlüsselte Verbindung verlangt.

… einen anderen Fehlercode, geh die in der CDO-Bibliothek definierten CdoErrors durch, um den Fehlernamen (Konstantennamen) zum numerischen/hexadezimalen Fehlercode zu finden. Dies kann einen Hinweis auf die Ursache des Problems geben.

Zeichensatz und Content-Transfer-Encoding

Eine E-Mail ist im Grunde eine Textdatei, die über das Netzwerk von einem Computer auf einen anderen übertragen wird. Wenn Textinformationen, die den Bereich von US-ASCII (7 Bit, nur 128 verschiedene Zeichen) überschreiten, zwischen verschiedenen Computern oder sogar verschiedenen Anwendungen übertragen werden, kann es zu Informationsverlusten oder Mehrdeutigkeiten bei der Interpretation der Informationen kommen.

Um Informationsverlust und Mehrdeutigkeit zu vermeiden, sollten E-Mail-Clients den Zeichensatz (Charset) des Textes angeben und können eine Angabe zur Kodierung des Inhalts verwenden. Standardmäßig verwendet CDO Content-Transfer-Encoding: 8bit und gibt keinen Zeichensatz an. Der E-Mail-Client, der die E-Mail für den Empfänger anzeigt, verwendet dann seinen Standardzeichensatz, um den Text anzuzeigen. – Dies kann bereits schiefgehen, wenn sich entweder Absender oder Empfänger außerhalb eines englischsprachigen Landes oder Westeuropas befinden. Es wird definitiv schief gehen, wenn der E-Mail-Text Zeichen außerhalb des grundlegenden 8-Bit-Bereichs (nur 256 Zeichen) enthält, z. B. asiatische, kyrillische oder arabische Zeichen. Jedes solche Zeichen wird dem Empfänger der E-Mail nur als Fragezeichen angezeigt.

Um solche Probleme zu vermeiden, gib einen Zeichensatz an, der alle im Text Ihrer E-Mail verwendeten Zeichen repräsentiert. Sofern du nicht nur einfaches Englisch schreibst, das durch US-ASCII dargestellt werden kann, ist UTF-8 wahrscheinlich die beste Wahl, das fast jedes vorhandene Zeichen mit einem relativ geringen Overhead abdeckt.

Hier ist ein Beispiel, das zeigt, wie Zeichensatz und Codierung für eine CDO-E-Mail angegeben werden.

With mail .To = "someone@somewhere.invalid" .From = "me@mycompany.invalid" .subject = "Email with CDO on GMail - None" .TextBody = "This is the body of a plain text email including the €-sign, " & _ "some German Umlauts ÄÜÖ äüö ß and " & _ "a bit of Japanese: " & ChrW(12402) & ChrW(12394) & ChrW(12364) & ChrW(12425) .BodyPart.Charset = CdoCharset.cdoUTF_8 .BodyPart.ContentTransferEncoding = CdoEncodingType.cdo8bit .Send End With

Beachten, dass die 8-Bit-Kodierung die Standardeinstellung ist und hier nur als Beispiel angegeben wird. Ich denke, in der heutigen Zeit kann man davon ausgehen, dass alle Software, die an der Verarbeitung der E-Mail beteiligt ist, 8-Bit-Textdaten verarbeiten kann. Nur wenn du damit rechnest, dass Ihre E-Mail über alte Legacy-Systeme übertragen wird, ist das Transfer Encoding Quoted Printable die bessere Wahl.

Erweiterte E-Mails mit HTML und Lese-/Zustellbestätigungen

CDO unterstützt auch erweiterte E-Mail-Eigenschaften wie HTML-Text, Priorität, Zustellungs- und Lesebestätigungen sowie benutzerdefinierte Header-Werte.

Um eine HTML-E-Mail zu senden, verwendest du einfach die HTMLBody-Eigenschaft anstelle von TextBody für den Text der Email.

With mail ' ... .HTMLBody = "<b>Hi!</b><br>This is a <i>wonderful</i> email with HTML!" ' ... End With

Die Fields-Auflistung des Message-Objekts kann viele zusätzliche Metainformationen zur E-Mail-Nachricht enthalten. Felder mit einem Namen aus der CdoMailHeader-Konstantenliste beschreiben Headerwerte der E-Mail. Dazu gehören die Anforderungen von Lese- und Zustellbestätigungen.

With mail .To = "someone@somewhere.invalid" .From = "me@mycompany.invalid" .subject = "Email with CDO on GMail - None" ' ... .Fields(CdoMailHeader.cdoDispositionNotificationTo).value = "someone.else@mycompany.invalid" .Fields(CdoMailHeader.cdoReturnReceiptTo).value = "me@mycompany.invalid" .Fields.Update .Send End With

Dadurch wird der E-Mail ein Disposition-Notification-to-Header (die Zustellbenachrichtigung) und ein Return-Receipt-to-Header (die Lesebestätigung) hinzugefügt.

Vorsicht mit Lese- und Zustellbestätigungen! Sie sind nicht zuverlässig. Es liegt im Ermessen des Empfängers und seiner Software, ob diese verarbeitet werden. Auch können die Wahrscheinlichkeit erhöhen, dass deine E-Mail als Junk-Mail eingestuft wird. Einige E-Mail-Server verweigern möglicherweise sogar die Annahme deiner E-Mail komplett, wenn sie eine Lese- oder Zustellbestätigungsanforderung enthält. Es gibt Berichte, dass Gmail dies tut.

Es gibt weitere nützliche vordefinierte Header in der CdoMailHeader-Liste. Du kannst den gleichen Mechanismus jedoch auch verwenden, um einen vollständig benutzerdefinierten E-Mail-Header hinzuzufügen.

With mail ' ... .Fields("urn:schemas:mailheader:X-SomethingCustom") = "Custom Information" .Fields.Update .Send End With

Nicht-Standard-Header sollten mit „X-“ beginnen, um sie von funktionalen Headern zu abzugrenzen, die in den offiziellen SMTP-Spezifikationen definiert sind.

Voraussetzungen und Vor- / Nachteile von CDO für Email

Die einzige Systemvoraussetzung ist die CDO-Bibliothek (cdosys.dll), die auf jeder Standardinstallation von Windows seit Windows 2000 vorhanden ist.

Vorteile

  • Die Methode ist unabhängig von der installierten Email Client Software

  • Sehr mächtig und viele Features

Nachteile

  • Die vollständige Konfiguration für den Email Account muss in der Access Anwendung verfügbar sein

  • Etwas komplizierter zu verwenden als DoCmd.SendObject und Outlook Automation

  • Es ist unklar, wie lange Microsoft diese Technologie weiterhin unterstützen wird

Download

Um es dir noch einfacher zu machen, diese Methode für den Emailversand zu verwenden, habe ich ein VBA-Modul mit dem Beispielcode hochgeladen. In diesem Modul sind alle Konstanten aus der CDO-Bibliothek ebenfalls lokal deklariert. Du musst also keinen Verweis auf die Bibliothek hinzufügen, sondern kannst einfach diese Modul in deiner Anwendung importieren und bis sofort startklar.

Share this article: Share on Facebook Tweet Share on LinkedIn Share on XING

Abonniere meinen Newsletter

*

Ich werde Deine Email-Addresse niemals weitergeben. Du kannst den Newsletter jederzeit abbestellen.
Die Emailliste wird bei Mailchimp in den USA gespeichert. Diese Auftragsverarbeitung ist vertraglich geregelt. Weitere Details in der Datenschutzerklärung.



© 1999 - 2021 by Philipp Stiefel - Datenschutzerklärung