Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by haas.homelinux.net...

Inhaltsverzeichnis
1 Einleitung
2 Überblick über Python
3 Die Arbeit mit Python
4 Der interaktive Modus
5 Grundlegendes zu Python-Programmen
6 Kontrollstrukturen
7 Das Laufzeitmodell
8 Basisdatentypen
9 Benutzerinteraktion und Dateizugriff
10 Funktionen
11 Modularisierung
12 Objektorientierung
13 Weitere Spracheigenschaften
14 Mathematik
15 Strings
16 Datum und Zeit
17 Schnittstelle zum Betriebssystem
18 Parallele Programmierung
19 Datenspeicherung
20 Netzwerkkommunikation
21 Debugging
22 Distribution von Python-Projekten
23 Optimierung
24 Grafische Benutzeroberflächen
25 Python als serverseitige Programmiersprache im WWW mit Django
26 Anbindung an andere Programmiersprachen
27 Insiderwissen
28 Zukunft von Python
A Anhang
Stichwort

Download:
- ZIP, ca. 4,8 MB
Buch bestellen
Ihre Meinung?

Spacer
 <<   zurück
Python von Peter Kaiser, Johannes Ernesti
Das umfassende Handbuch - Aktuell zu Python 2.5
Buch: Python

Python
gebunden, mit CD
819 S., 39,90 Euro
Galileo Computing
ISBN 978-3-8362-1110-9
Pfeil 20 Netzwerkkommunikation
  Pfeil 20.1 Socket API
    Pfeil 20.1.1 Client/Server-Systeme
    Pfeil 20.1.2 UDP
    Pfeil 20.1.3 TCP
    Pfeil 20.1.4 Blockierende und nicht-blockierende Sockets
    Pfeil 20.1.5 Verwendung des Moduls
    Pfeil 20.1.6 Netzwerk-Byte-Order
    Pfeil 20.1.7 Multiplexende Server – select
    Pfeil 20.1.8 SocketServer
  Pfeil 20.2 Zugriff auf Ressourcen im Internet – urllib
    Pfeil 20.2.1 Verwendung des Moduls
  Pfeil 20.3 Einlesen einer URL – urlparse
  Pfeil 20.4 FTP – ftplib
  Pfeil 20.5 E-Mail
    Pfeil 20.5.1 SMTP – smtplib
    Pfeil 20.5.2 POP3 – poplib
    Pfeil 20.5.3 IMAP4 – imaplib
    Pfeil 20.5.4 Erstellen komplexer E-Mails – email
  Pfeil 20.6 Telnet – telnetlib
  Pfeil 20.7 XML-RPC
    Pfeil 20.7.1 Der Server
    Pfeil 20.7.2 Der Client
    Pfeil 20.7.3 Multicall
    Pfeil 20.7.4 Einschränkungen


Galileo Computing - Zum Seitenanfang

20.5 E-Mail  Zur nächsten ÜberschriftZur vorigen Überschrift

In diesem Abschnitt werden wir Module der Standardbibliothek vorstellen, die es ermöglichen, mit einem E-Mail-Server zu kommunizieren, das heißt E-Mails von diesem abzuholen bzw. E-Mails über den Server zu versenden.

Das Versenden einer E-Mail geschieht über einen sogenannten SMTP-Server, mit dem über ein gleichnamiges Protokoll kommuniziert werden kann. Im ersten Unterabschnitt werden wir deshalb das Modul smtplib der Standardbibliothek vorstellen, das genau dieses Kommunikationsprotokoll implementiert.

Für das Herunterladen einer empfangenen E-Mail gibt es zwei verbreitete Möglichkeiten: das POP3- und das IMAP4-Protokoll. Beide können mit dem jeweiligen Modul poplib bzw. imaplib verwendet werden.

Im letzten Abschnitt soll das Modul email der Standardbibliothek besprochen werden, das es über die MIME-Kodierung ermöglicht, beliebige Dateien (üblicherweise Bilder oder Dokumente) mit der E-Mail zu versenden.


Galileo Computing - Zum Seitenanfang

20.5.1 SMTP – smtplib  Zur nächsten ÜberschriftZur vorigen Überschrift

Das sogenannte SMTP-Protokoll (für Simple Mail Transfer Protocol) wird zum Versenden einer E-Mail über einen SMTP-Server verwendet. Das SMTP-Protokoll ist ähnlich wie FTP ein textbasiertes, lesbares Protokoll. Ursprünglich bot das SMTP-Protokoll keine Möglichkeit zur Authentifizierung des angemeldeten Benutzers durch Benutzername und Passwort beispielsweise. Dies war bei der rasanten Entwicklung des Internets ziemlich schnell nicht mehr tragbar, und so wurde das SMTP-Protokoll um den ESMTP-Standard (Extended SMTP) erweitert.

Ähnlich wie im Abschnitt über das FTP-Protokoll möchten wir hier zunächst eine Übersicht über die wichtigsten SMTP-Befehle geben. Die Befehle sind in der folgenden Tabelle in der Reihenfolge ihrer Benutzung in einer SMTP-Sitzung aufgelistet und werden jeweils mit einem kurzen Satz erklärt.


Tabelle 20.6  SMTP-Befehle
Befehl Beschreibung

HELO

Startet eine SMTP-Sitzung.

EHLO

Startet eine ESMTP-Sitzung

MAIL FROM

Leitet das Absenden einer E-Mail ein. Diesem Kommando wird die Absenderadresse beigefügt.

RCPT TO

Fügt einen Empfänger der E-Mail hinzu. (RCPT steht für »recipient«, dt. »Empfänger«.)

DATA

Mit diesem Kommando wird der Inhalt der E-Mail angegeben und die Mail schlussendlich verschickt.

QUIT

Beendet die SMTP- bzw. ESMTP-Sitzung.


Wie schon die ftplib enthält das Modul smtplib im Wesentlichen nur eine Klasse namens SMTP. Über diese Klasse läuft, nachdem sie instanziiert wurde, alle weitere Kommunikation mit dem Server. Der Konstruktor der Klasse SMTP hat folgende Schnittstelle:

smtplib.SMTP([host[, port[, local_hostname]]])

Erzeugt eine Instanz der Klasse SMTP. Optional können hier bereits die Verbindungsdaten zum SMTP-Server übergeben werden. Beachten Sie, dass Sie den Port nur explizit anzugeben brauchen, wenn er sich vom SMTP-Standardport 25 unterscheidet.

Als dritter Parameter kann der Domainname des lokalen Hosts übergeben werden. Dieser wird dem SMTP-Server als Identifikation im ersten gesendeten Kommando übermittelt. Wenn der Parameter local_hostname nicht angegeben wird, wird versucht, den lokalen Hostnamen automatisch zu ermitteln.

Die Klasse SMTP

Im Folgenden sollen die wichtigsten Methoden der SMTP-Klasse erläutert werden. Um die Beispiele dieses Abschnitts nachvollziehen zu können, muss das Modul smtplib eingebunden werden und eine Instanz der Klasse SMTP mit dem Namen s existieren. Für die meisten der Beispiele muss die SMTP-Instanz zusätzlich mit einem Server verbunden und angemeldet sein.

s.connect([host[, port]])

Verbindet zum SMTP-Server host mit der Portnummer port. Diese Methode sollte nicht aufgerufen werden, wenn bei der Instanziierung der SMTP-Klasse bereits Verbindungsdaten übergeben wurden. Wenn keine Verbindung zum SMTP-Server aufgebaut werden kann, wird eine Exception geworfen.

>>> s.connect("smtp.knallhart.de") 
(220, 'Die Botschaft des Servers')
s.login(user, password)

Diese Methode ermöglicht es, sich beim SMTP-Server mit dem Benutzernamen user und dem Passwort password einzuloggen, sofern der Server dies verlangt.

>>> s.login("Benutzername", "Passwort") 
(235, '2.0.0 Authentication successful')

Im Fehlerfall können folgende Exceptions geworfen werden:


Tabelle 20.7  Mögliche Exceptions beim Login
Exception Beschreibung

SMTPHeloError

Der SMTP-Server hat nicht oder nicht richtig auf das Begrüßungskommando HELO geantwortet.

SMTPAuthenticationError

Die angegebene Benutzername/Passwort-Kombination wurde vom SMTP-Server nicht akzeptiert.

SMTPError

Es wurde keine Möglichkeit gefunden, eine Authentifizierung bei diesem SMTP-Server durchzuführen.


s.sendmail(from_addr, to_addr, msg[, mail_options, rctp_options])

Durch Aufruf der Methode sendmail kann eine E-Mail über den SMTP-Server versendet werden. Beachten Sie, dass die SMTP-Instanz dafür an einem SMTP-Server angemeldet und zumeist auch authentifiziert sein muss.

Die ersten beiden Parameter enthalten die E-Mail-Adressen des Absenders (from_addr) bzw. eine Liste der E-Mail-Adressen der Empfänger (to_addr). Als E-Mail-Adresse wird dabei ein String des folgenden Formats bezeichnet:

Vorname Nachname <em@il.addr>

Alternativ kann auch nur die E-Mail-Adresse an sich im String stehen.

Als dritter Parameter, msg, wird der Text der E-Mail übergeben. Beachten Sie, dass weitere Angaben wie beispielsweise der Betreff der E-Mail innerhalb des E–Mail-Bodys definiert werden. Wie so etwas genau aussieht und welche Möglichkeiten Python bietet, diesen Header komfortabel zu erzeugen, erfahren Sie in Abschnitt 20.5.4.

Die Methode sendmail gibt stets ein Dictionary zurück, in dem alle Empfänger, die vom SMTP-Server zurückgewiesen wurden, als Schlüssel enthalten sind und der jeweilige Error-Code mit Fehlerbezeichnung als Wert aufgeführt ist. Wenn alle Empfänger die E-Mail bekommen haben, ist das zurückgegebene Dictionary leer.

Im Fehlerfall wirft die Methode sendmail folgende Exceptions:


Tabelle 20.8  Mögliche Exceptions beim Login
Exception Beschreibung
SMTPHeloError

Der SMTP-Server hat nicht oder nicht richtig auf das Begrüßungskommando HELO geantwortet.

SMTPRecipientsRefused

Alle Empfänger wurden vom SMTP-Server zurückgewiesen. Das heißt, dass die E-Mail tatsächlich an niemanden verschickt wurde.

Als Attribut enthält die Exception ein Dictionary, das demjenigen ähnelt, das von sendmail im Erfolgsfall zurückgegeben wird.

SMTPSenderRefused

Der angegebene Absender wurde vom SMTP-Server zurückgewiesen.

SMTPDataError

Der Server hat mit einem unerwarteten Fehler geantwortet.


Beachten Sie, dass der Text einer E-Mail nur aus ASCII-Zeichen bestehen darf. Um auch andere Zeichen und insbesondere auch Binärdaten verschicken zu können, bedient man sich der sogenannten MIME-Kodierung, die wir im Kapitel email behandeln werden.

Über die optionalen Parameter mail_options und rctp_options kann je eine Liste von Strings übergeben werden, die Optionen des ESMTP-Standards (Extended SMTP) enthalten. Die für mail_options übergebenen Optionen werden dem Kommando MAIL FROM angefügt; hier wäre beispielsweise die Option "8bitmime" sinnvoll. Alle für rctp_options übergebenen Optionen werden dem Kommando RCPTTO angehängt, wo beispielsweise die Option "DSN" verwendet werden könnte.

Welche Optionen im ESMTP-Standard definiert werden und was diese bedeuten, soll nicht Thema dieses Buches sein. Wenn Sie sich dafür interessieren, fühlen Sie sich dazu ermutigt, unter den genannten Stichwörtern im Internet zu recherchieren.

s.quit()

Beendet die Verbindung zum SMTP-Server.

Beispiel

Nachdem die wichtigsten Methoden einer SMTP-Instanz erläutert wurden, folgt nun ein kleines Beispiel, in dem zu einem SMTP-Server verbunden wird, um zwei E-Mails an verschiedene Empfänger zu verschicken:

>>> smtp = smtplib.SMTP("smtp.hostname.de") 
>>> smtp.login("benutzername", "passwort") 
(235, '2.0.0 Authentication successful') 
>>> smtp.sendmail( 
...               "Peter Kaiser <p@penguin-p.de>", 
...               "Johannes Ernesti <je@revelation-soft.de>", 
...               "Dies ist der Text") 
{} 
>>> smtp.sendmail( 
...               "Peter Kaiser <p@penguin-p.de>", 
...               ["je@revelation-soft.de", "p@penguin-p.de"] 
...               "Dies ist der Text") 
{} 
>>> smtp.quit()

Bei der ersten E-Mail wurden die vollen Namen des Absenders bzw. des Empfängers angegeben. Das zweite Beispiel zeigt, dass auch die E-Mail-Adresse allein reicht und wie eine E-Mail an mehrere Empfänger versandt werden kann.


Galileo Computing - Zum Seitenanfang

20.5.2 POP3 – poplib  Zur nächsten ÜberschriftZur vorigen Überschrift

Nachdem anhand der smtplib erläutert wurde, wie E-Mails über einen SMTP-Server versandt werden können, soll das Thema dieses Kapitels das Modul poplib der Standardbibliothek sein. Dieses Modul implementiert das POP3-Protokoll (Post Office Protocol Version 3). Bei POP3 handelt es sich um ein Protokoll, um auf einen POP3-Server zuzugreifen und dort gespeicherte E-Mails einzusehen und abzuholen. Das POP3-Protokoll steht damit in Konkurrenz zu IMAP4, dessen Benutzung mit der imaplib das Thema des nächsten Abschnitts sein soll. Die folgende Tabelle listet die wichtigsten POP3-Kommandos mit ihrer Bedeutung auf. Die Befehle stehen dabei in der Reihenfolge, wie sie in einer üblichen POP3-Sitzung verwendet werden.


Tabelle 20.9  POP3-Befehle
Befehl Beschreibung
USER

Überträgt den Benutzernamen zur Authentifizierung auf dem Server.

PASS

Überträgt das Passwort zur Authentifizierung auf dem Server.

STAT

Liefert den Status des Posteingangs, beispielsweise die Anzahl der neu eingegangenen E-Mails.

LIST

Liefert Informationen zu einer bestimmten E-Mail des Posteingangs.

RETR

Überträgt eine bestimmte E-Mail.

DELE

Löscht eine bestimmte E-Mail.

RSET

Löschvorgänge werden gepuffert und erst am Ende der Sitzung ausgeführt. Mit diesem Kommando können alle anstehenden Löschvorgänge widerrufen werden.

QUIT

Beendet die POP3-Sitzung.


Wie bereits beim Modul smtplib ist im Modul poplib im Wesentlichen die Klasse POP3 enthalten, die instanziiert werden muss, bevor Operationen auf einem POP3-Server durchgeführt werden können. Die Schnittstelle des Konstruktors sieht folgendermaßen aus:

poplib.POP3(host[, port])

Erzeugt eine Instanz der Klasse POP3. Dem Konstruktor wird der Hostname des POP3-Servers übergeben, zu dem verbunden werden soll. Optional kann ein Port angegeben werden, wenn dieser sich vom voreingestellten Standardport 110 unterscheidet.

Die Klasse POP3

Im Folgenden sollen die wichtigsten Methoden der Klasse POP3 beschrieben werden. Die Funktionsnamen entsprechen im Wesentlichen den POP3-Befehlen, die sie senden. Um die in diesem Abschnitt vorgestellten Beispiele ausführen zu können, muss zum einen das Modul poplib eingebunden sein und zum anderen eine Instanz der Klasse POP3 mit dem Namen pop existieren. Beachten Sie, dass diese Instanz für die meisten Beispiele mit einem POP3-Server verbunden und bei diesem authentifiziert sein muss.

pop.user(username)

Übermittelt den Benutzernamen username an den POP3-Server. Die Antwort des Servers ist in der Regel ein String, in dem er ein Passwort fordert. Das angeforderte Passwort kann jetzt durch einen Aufruf der Methode pass_ übermittelt werden. Beachten Sie, dass ein falscher Benutzername zunächst nicht zu einer Exception führt.

>>> pop.user("Benutzername") 
'+OK Password required.'
pop.pass_(password)

Übermittelt das Passwort password an den POP3-Server. Nachdem das Passwort vom Server akzeptiert worden ist, darf auf den Posteingang zugegriffen werden. Dieser ist bis zum Aufruf von quit für andere Login-Versuche gesperrt.

>>> pop.pass_("Passwort") 
'+OK logged in.'

Im Falle einer fehlgeschlagenen Authentifizierung wird eine poplib.error_proto-Exception geworfen.

pop.stat()

Gibt den Status des Posteingangs zurück. Das Ergebnis ist ein Tupel mit zwei ganzen Zahlen: der Anzahl der enthaltenen Nachrichten und der Größe des Posteingangs.

>>> pop.stat() 
(1, 623)

In diesem Fall befindet sich eine E-Mail im Posteingang, und die Gesamtgröße des Posteingangs beläuft sich auf 623 Byte.

pop.list([which])

Gibt eine Liste der im Posteingang liegenden Mails zurück. Der Rückgabewert dieser Methode ist ein Tupel der folgenden Form:

(antwort, ["mailID laenge", ...], datlen)

Dabei enthält das Tupel als erstes Element den Antwortstring des Servers und als zweites Element eine Liste von Strings, die je für eine E-Mail des Posteingangs stehen. Im String sind zwei Angaben enthalten. Die Angabe mailID ist die laufende Nummer der Mail, eine Art Index, und laenge ist die Gesamtgröße der Mail in Byte. In Bezug auf den Index sollten Sie beachten, dass alle E-Mails auf dem Server fortlaufend von 1 an indiziert werden und nicht, wie bei einer Python-Liste beispielsweise, mit 0 beginnend.

Das erste Element des Tupels (antwort) enthält dabei nicht den vollständigen Antwortstring des Servers, denn die Informationen, die zum zweiten Element des Tupels aufbereitet wurden, wurden aus antwort entfernt. Um dennoch die komplette Länge der Serverantwort berechnen zu können, existiert das dritte Element des Tupels (datlen). Dieses referenziert die Länge des Datenbereichs der Antwort des Servers. Damit entspräche len(antwort) + datlen der Gesamtgröße des vom Server tatsächlich gesendeten Antwortstrings.

Über den optionalen Parameter which kann die laufende Nummer einer E-Mail angegeben werden, über die nähere Informationen zurückgegeben werden sollen. In diesem Fall gibt die Methode einen String des Formats "+OK mailID laenge" zurück. Es ist also mit dieser Methode nur möglich, die Länge einer bestimmten E-Mail in Byte herauszufinden, da die ID ja bereits bekannt ist. Wenn eine ungültige ID für which übergeben wurde, wird eine poplib.error_proto-Exception geworfen.

>>> pop.list() 
('+OK […].', ['1 623'], 7) 
>>> pop.list(1) 
'+OK 1 623'
pop.retr(which)

Greift auf die Mail mit der laufenden Nummer which zu und gibt ihren Inhalt in Form des folgenden Tupels zurück:

(antwort, zeilen, laenge)

Das erste Element des Tupels entspricht dem Antwortstring des Servers. An zweiter Stelle steht eine Liste von Strings, die je eine Zeile der E-Mail inklusive des E–Mail-Headers enthalten. Das letzte Element des Tupels ist die Größe der E-Mail in Byte.

>>> pop.retr(1) 
('+OK 623 octets follow.', […], 623)

Anstelle des Auslassungszeichens stünde eine Liste von Strings, die die Zeilen der vollständigen E-Mail enthält.

pop.dele(which)

Löscht die Mail mit der laufenden Nummer which vom POP3-Server. Beachten Sie, dass die meisten Server solche Befehle puffern und erst nach Aufruf der Methode quit tatsächlich ausführen.

>>> pop.dele(1) 
'+OK Deleted.'
pop.rset()

Ein Aufruf dieser Methode veranlasst, dass alle anstehenden Löschvorgänge verworfen werden.

>>> pop.rset() 
'+OK Resurrected.'
pop.quit()

Beendet die Verbindung zum POP3-Server. Bei den meisten Servern werden erst jetzt alle anstehenden Löschvorgänge durchgeführt.

>>> pop.quit() 
'+OK Bye-bye.'

Beispiel

Nachdem die wichtigsten Methoden einer POP3-Instanz erklärt wurden, werden wir hier in einem kleinen Beispiel das Modul poplib dazu verwenden, alle Mails von einem POP3-Server abzuholen und auf dem Bildschirm anzuzeigen:

import poplib
pop = poplib.POP3("pop.hostname.de") pop.user("benutzername") pop.pass_("passwort")
for i in xrange(1, pop.stat()[0]+1): for zeile in pop.retr(i)[1]: print zeile print "***"
pop.quit()

Zunächst wird eine Instanz der Klasse POP3 erzeugt und das Programm meldet sich mit den Methoden user und pass_ beim POP3-Server an. Der Ausdruck pop.stat()[0] liefert die Zahl der Mails, die sich im Posteingang befinden. In der for-Schleife werden also alle Mail-Indizes durchlaufen. Beachten Sie dazu, dass die Indizes der E-Mails im Posteingang mit 1 beginnen.

In der inneren Schleife wird die jeweils aktuelle Mail mit dem Index i durch Aufruf der Methode retr heruntergeladen. Das zweite Element, also das mit dem Index 1 des von dieser Methode zurückgegebenen Tupels, enthält eine Liste mit allen Zeilen des Mail-Inhalts. Diese Liste wird in der Schleife durchlaufen, und es wird jeweils die aktuelle Zeile ausgegeben.

Beachten Sie, dass im Beispielprogramm aus Gründen der Übersichtlichkeit auf jegliche Fehlerbehandlung verzichtet wurde. In einem fertigen Programm müssten Sie auf jeden Fall prüfen, ob die Verbindung zum Server hergestellt werden konnte und ob die Authentifizierung erfolgreich war.

Nachdem eine E-Mail vollständig durchlaufen worden ist, werden drei Sternchen ausgegeben, die damit als eine Art Trennlinie zwischen den Mails fungieren.


Galileo Computing - Zum Seitenanfang

20.5.3 IMAP4 – imaplib  Zur nächsten ÜberschriftZur vorigen Überschrift

Das Modul imaplib stellt die Klasse IMAP4 zur Verfügung, mit deren Hilfe man eine Verbindung zu einem IMAP4-Server herstellen und mit diesem kommunizieren kann. Das IMAP4-Protokoll (Internet Message Access Protocol 4) ist ähnlich wie das POP3-Protokoll zur Verwaltung von E-Mails auf einem Mailserver gedacht. Anders als bei dem bekannteren Protokoll POP3 verbleiben die E-Mails bei IMAP4 zumeist auf dem Mailserver, was den Vorteil hat, dass man von überall – beispielsweise auch von einem Internet-Cafe im Urlaub aus – vollen Zugriff auf alle archivierten E-Mails hat. Heutzutage bieten die meisten E-Mail-Anbieter sowohl einen POP3- als auch einen IMAP4-Zugang an. Im Vergleich zu POP3 unterstützt IMAP4 Kommandos zur komfortablen Verwaltung der Mails auf dem Server. So können beispielsweise Unterordner angelegt werden.

Im Gegensatz zu den bisherigen Protokollen wie FTP oder POP3 ist IMAP4 mit einem hohen Funktionsumfang ausgestattet, und obwohl das Protokoll immer noch auf lesbaren Textnachrichten basiert, ist es zu komplex, um es im Stil der bisherigen Abschnitten mit einem kurzen Text und einer Tabelle ausreichend zu beschreiben. Grundsätzlich kann aber gesagt werden, dass das IMAP4-Protokoll umfassende Unterstützung zur Verwaltung der E-Mails bereitstellt. So lassen sich diese beispielsweise in verschiedene sogenannte Mailboxen einsortieren. Dabei kann man sich eine Mailbox als eine Art Verzeichnis vorstellen, das E-Mails enthalten kann, wie ein Ordner Dateien enthält. Die Mailbox-Struktur des verwendeten Beispielservers sieht folgendermaßen aus:

Abbildung 20.3  Mailbox-Struktur des Beispielservers

Es existieren eine übergeordnete Mailbox namens INBOX sowie zwei untergeordnete Mailboxen namens INBOX.Ham und INBOX.Spam.

Um eine Verbindung zu einem IMAP4-Server herstellen zu können, muss eine Instanz der Klasse IMAP4 erzeugt werden. Der Konstruktor dieser Klasse hat folgende Schnittstelle:

imaplib.IMAP4([host[, port]])

Erzeugt eine Instanz der Klasse IMAP4. Optional kann direkt nach der Instanziierung automatisch eine Verbindung zu einem IMAP4-Server mit dem Hostnamen host unter Verwendung des Ports port aufgebaut werden. Wenn der Parameter port nicht angegeben wurde, wird der IMAP4-Standardport 143 verwendet.

Die Klasse IMAP4

Nachdem eine Instanz der Klasse IMAP4 erzeugt wurde, stellt diese verschiedene Methoden bereit, um mit dem verbundenen Server zu kommunizieren. Jede Methode, die ein IMAP4-Kommando repräsentiert, gibt ein Tupel der folgenden Form zurück:

(Status, [Daten, …])

Dabei steht im resultierenden Tupel für Status entweder "OK" oder "NO", je nachdem, ob die Operation erfolgreich verlaufen oder fehlgeschlagen ist. Das zweite Element des Tupels ist eine Liste, die die Daten enthält, die der Server als Antwort geschickt hat. Diese Daten können entweder ebenfalls ein String oder ein Tupel sein. Wenn es sich um ein Tupel handelt, verfügt dieses über zwei Elemente:

(Header, Daten)

Beide Elemente dieses Tupels sind Strings. Im Folgenden sollen die wichtigsten Methoden einer IMAP4-Instanz erläutert werden. Die Beispiele setzen zumeist eine verbundene IMAP4-Instanz im voraus:

>>> import imaplib 
>>> im = imaplib.IMAP4("imap.test.de")

In den meisten Fällen muss die IMAP4-Instanz zudem beim Server eingeloggt sein, was durch Aufruf der Methode login geschieht.

im.login(user, password)

Sendet Benutzername und Passwort an den verbundenen IMAP4-Server.

>>> im.login("Benutzername", "Passwort") 
('OK', ['LOGIN Ok.'])
im.logout()

Beendet die Verbindung zum IMAP4-Server.

>>> im.logout() 
('BYE', ['Courier-IMAP server shutting down'])
im.select([mailbox[, readonly]])

Wählt eine Mailbox aus, um weitere Operationen auf dieser durchführen zu können. Dabei wird als erster Parameter der Name der auszuwählenden Mailbox übergeben. Wenn für den Parameter readonly 1 übergeben wird, ist die gewählte Mailbox bei diesem Zugriff schreibgeschützt und kann somit nicht verändert werden. Die Funktion select gibt die Anzahl der E-Mails zurück, die sich in der gewählten Mailbox befinden.

>>> im.select("INBOX") 
('OK', ['2'])

Beachten Sie, dass keine Exception geworfen wird, wenn die gewünschte Mailbox nicht existiert, sondern dass der Fehler anhand des Rückgabewertes ausgemacht werden muss:

>>> im.select("INBOX.NichtExistent") 
('NO', ['Mailbox does not exist, or must be subscribed to.'])
im.close()

Schließt die momentan ausgewählte Mailbox.

>>> im.close() 
('OK', ['mailbox closed.'])
im.list([directory[, pattern]])

Gibt die Namen aller Mailboxen zurück, die sich im Ordner directory befinden und auf pattern passen. Wenn der Parameter directory nicht übergeben wird, werden Mailboxen des Hauptordners zurückgegeben. Sollte der zweite Parameter pattern nicht übergeben werden, so werden alle im jeweiligen Ordner enthaltenen Mailboxen zurückgegeben. Der Parameter pattern muss ein String sein und enthält üblicherweise Fragmente eines Mailbox-Namens inklusive Platzhalter (*).

>>> im.list(".", "*Ham") 
('OK', ['(\\HasNoChildren) "." "INBOX.Ham"']) 
>>> im.list(".", "*am") 
('OK', ['(\\HasNoChildren) "." "INBOX.Ham"', 
'(\\HasNoChildren) "." "INBOX.Spam"']) 
>>> im.list(".", "*") 
('OK', ['(\\HasNoChildren) "." "INBOX.Ham"', 
'(\\HasNoChildren) "." "INBOX.Spam"', 
'(\\Unmarked \\HasChildren) "." "INBOX"']) 
>>> im.list(".", "NichtVorhandeneMailbox") 
('OK', [None])

Jeder Eintrag der Liste ist ein String und enthält drei, jeweils durch ein Leerzeichen voneinander getrennte Informationen: die sogenannten Flags der Mailbox in Klammern, das Verzeichnis der Mailbox und der Mailbox-Name jeweils in doppelten Anführungsstrichen. Aus den Flags kann man beispielsweise die Information entnehmen, ob eine Mailbox untergeordnete Mailboxen enthält (\HasChildren) oder nicht (\HasNoChildren).

im.fetch(message_set, message_parts)

Lädt Teile der E-Mails vom Server herunter. Der Parameter message_set muss ein String sein, der die Mail-IDs der E-Mails enthält, die herunterzuladen sind. Dabei können diese entweder einzeln im String vorkommen ("1"), als Bereich ("1:4" für Mail Nr.1 bis 4), als Liste von Bereichen ("1:4,7:9" für Mail Nr.1 bis 4 und Nr.7 bis 9) oder als Bereich mit unbestimmter oberer Grenze ("3:*" für alle Mails ab Mail Nr.3).

Wenn andere Methoden der IMAP4-Klasse über einen Parameter message_set verfügen, so ist damit stets ein String im oben beschriebenen Format gemeint.

Der zweite Parameter message_parts kennzeichnet, welche Teile der angegebenen E-Mails heruntergeladen werden sollen. Ein Wert von "(RCF822)" bedeutet, die gesamte Mail, also inklusive des Mail-Headers herunterzuladen. Bei einem Wert von "(BODY[TEXT])" würde hingegen nur der Text und bei "(BODY[HEA DER])" nur der Header der E-Mail heruntergeladen.

Ein Aufruf der Methode fetch funktioniert nur, wenn zuvor eine Mailbox mittels select ausgewählt wurde.

>>> im.fetch("1", "(BODY[TEXT])") 
('OK', [('1 (BODY[TEXT] {29}', 
'Dies ist eine Testnachricht\r\n'), ')'])
>>> im.fetch("1:2", "(BODY[TEXT])") ('OK', [('1 (BODY[TEXT] {29}', 'Dies ist eine Testnachricht\r\n'), ')', ('2 (BODY[TEXT] {25}', 'Noch eine Testnachricht\r\n'), ')'])

Im Falle einer nicht vorhandenen Mail-ID wird keine Exception geworfen, sondern schlicht ein leeres Ergebnis zurückgegeben. Wenn die ID ungültig ist, kommt eine entsprechende Fehlermeldung zurück.

>>> im.fetch("100", "(BODY[TEXT])") 
('OK', [None]) 
>>> im.fetch("KeineID", "(BODY[TEXT])") 
('NO', ['Error in IMAP command received by server.'])
im.create(mailbox)

Erstellt eine neue Mailbox namens mailbox.

>>> im.create("INBOX.Hallo") 
('OK', ['"INBOX.Hallo" created.'])
im.delete(mailbox)

Löscht die Mailbox mailbox.

>>> im.delete("INBOX.Hallo") 
('OK', ['Folder deleted.'])
im.rename(old_mailbox, new_mailbox)

Benennt die Mailbox old_mailbox in new_mailbox um.

>>> im.rename("INBOX.Hallo", "INBOX.Ciao") 
('OK', ['Folder renamed.'])
im.copy(message_set, new_mailbox)

Kopiert die E-Mails message_set in die Mailbox new_mailbox.

im.search(charset, criterion[, …])

Sucht innerhalb der ausgewählten Mailbox nach E-Mails, die auf die angegebenen Kriterien passen. Als Kriterium criterion kann entweder der String "ALL" (alle Mails erfüllen dieses Kriterium) oder ein String des Formats "(FROM \"Johannes\")" verwendet werden. Das zweite Kriterium ist für alle Mails erfüllt, die von einem gewissen Johannes geschrieben wurden.

Der Parameter charset spezifiziert das Encoding von criterion in Form eines Strings. Üblicherweise wird der Parameter charset nicht benötigt und None übergeben.

Die Funktion search gibt die IDs der gefundenen E-Mails in Form einer Liste zurück.

>>> im.search(None, "(FROM \"Johannes\")") 
('OK', ['1 2 3']) 
>>> im.search(None, "(FROM \"Johann\")") 
('OK', ['1 2 3']) 
>>> im.search(None, "(FROM \"Johanninski\")") 
('OK', [''])

Beispiel

Im folgenden Beispielprogramm soll das Modul imaplib dazu verwendet werden, zu einem IMAP4-Server zu verbinden und alle enthaltenen E-Mails einer bestimmten Mailbox anzuzeigen. Dabei soll dem Benutzer die Möglichkeit gegeben werden, die Mailbox zu wählen.

Der Quelltext des Beispielprogramms sieht folgendermaßen aus:

import imaplib
im = imaplib.IMAP4("Hostname") im.login("Benutzername", "Passwort")
print "Vorhandene Mailboxen:" for mb in im.list()[1]: name = mb.split("\".\"")[-1] print " - %s" % name.strip(" \"")
mb = raw_input("Welche Mailbox soll angezeigt werden: ") im.select(mb) status, daten = im.search(None, "ALL") for mailnr in daten[0].split(): typ, daten = im.fetch(mailnr, "(RFC822)") print "%s\n+++\n" % daten[0][1]
im.close() im.logout()

Zunächst wird eine Instanz der Klasse IMAP4 erzeugt und zu einem IMAP4-Server verbunden. Dann werden mithilfe der Methode list alle im Hauptordner des IMAP4-Kontos vorhandenen Mailboxen durchlaufen und die Namen der Mailboxen auf dem Bildschirm angezeigt. Dabei ist zu beachten, dass die Methode list die Namen der Mailboxen mit zusätzlichen Informationen zurückgibt. Diese Informationen müssen herausgefiltert werden, bevor der Mailboxname angezeigt werden kann. Nachdem die Namen angezeigt wurden, wird der Benutzer dazu aufgefordert, einen der angegebenen Mailbox-Namen auszuwählen.

Die vom Benutzer ausgewählte Mailbox wird dann mithilfe der Methode select auch auf dem Server ausgewählt. Der danach aufgerufenen Methode search wird der String "ALL" übergeben, was den Mailserver dazu veranlasst, Daten über alle E-Mails der ausgewählten Mailbox zurückzugeben.

Danach iterieren wir in einer for-Schleife über die Liste von Mail-IDs, die search zurückgegeben hat, und laden die jeweilige Mail mittels fetch vollständig herunter. Die heruntergeladene Mail wird auf dem Bildschirm ausgegeben.

Schlussendlich schließen wir die ausgewählte Mailbox und beenden die Verbindung mit dem Server.

Beachten Sie auch bei diesem Beispielprogramm, dass keine Fehlerbehandlung durchgeführt wurde. In einem fertigen Programm sollten sowohl die Verbindungsanfrage als auch das Login und insbesondere auch die Benutzereingabe überprüft werden.


Galileo Computing - Zum Seitenanfang

20.5.4 Erstellen komplexer E-Mails – email  topZur vorigen Überschrift

In den vorherigen Kapiteln wurde besprochen, wie E-Mails über einen SMTP-Server versendet und von einem POP3- oder IMAP4-Server heruntergeladen werden können. Trotz alledem bleibt eine Frage weiterhin offen: Wie Sie wissen, basiert das Senden und Empfangen von E-Mails auf reinen ASCII-Protokollen. Das bedeutet vor allem, dass mit diesen Protokollen keine Binärdaten verschickt werden können. Außerdem sind Sonderzeichen, die nicht dem 7-Bit-ASCII-Standard entsprechen, problematisch.

Um also solche Zeichen oder Binärdaten verschicken zu können, wurde der sogenannte MIME-Standard (Multipurpose Internet Mail Extension) entwickelt, der Sonderzeichen und Binärdaten so kodiert, dass sie als eine Folge reiner ASCII-Zeichen versandt werden können. Durch eine solche Form der Kodierung steigt allerdings die Größe der zu übermittelnden Daten. Zudem definiert der MIME-Standard verschiedene Dateitypen und legt eine Syntax fest, mit der Dateianhänge einem bestimmten Dateityp zugeordnet werden, sodass die Dateien beim Empfänger leichter verarbeitet werden können.

Das email-Paket ist sehr mächtig, weswegen hier nur ein Teil seiner Funktionalität besprochen werden kann. Zunächst werden wir uns darum kümmern, wie eine simple ASCII-Mail mittels email erstellt werden kann. Darauf aufbauend werden wir zu komplexeren MIME-kodierten Mails übergehen.

Erstellen einer einfachen E-Mail

Als Basisklasse für eine neue E-Mail dient die Klasse Message des Moduls email.message. Das folgende Beispielprogramm zeigt, wie sie zu verwenden ist:

from email.message import Message
msg = Message() msg.set_payload("Dies ist meine selbst erstelle E-Mail.") msg["Subject"] = "Hallo Welt" msg["From"] = "Donald Duck <don@ld.de>" msg["To"] = "Onkel Dagobert <d@gobert.de>"
print msg.as_string()

Zunächst wird eine Instanz der Klasse Message erzeugt. Der Konstruktor dieser Klasse erwartet keine Argumente. Durch die Methode set_payload (dt. Nutzlast) wird der E-Mail ein Text hinzugefügt.

Jetzt fehlt nur noch der E-Mail-Header. Um diesen hinzuzufügen, kann die Message-Instanz wie ein Dictionary angesprochen werden. Auf diese Weise werden die einzelnen Teile des Headers hinzugefügt. Wichtig sind dabei "Subject" für den Betreff, "From" für den Absender und "To" für den Empfänger der Mail.

Zu guter Letzt wird die entstandene E-Mail durch die Methode as_string in einen String geschrieben und ausgegeben. Dieser String könnte der Methode sendmail des Moduls smtplib übergeben und somit als E-Mail verschickt werden. Die Ausgabe des Beispielprogramms, also die erzeugte E-Mail, sieht folgendermaßen aus:

Subject: Hallo Welt 
From: Donald Duck <don@ld.de> 
To: Onkel Dagobert <d@gobert.de> 
 
Dies ist meine selbst erstelle E-Mail.

Erstellen einer E-Mail mit Anhängen

Wir haben angekündigt, dass es das Paket email ermöglicht, Binärdaten per E–Mail zu verschicken. Dafür ist das Modul email.mime zuständig. Das folgende Beispielprogramm soll eine E-Mail erstellen und eine Bilddatei als Anhang einfügen.

from email.mime.multipart import MIMEMultipart 
from email.mime.image import MIMEImage 
from email.mime.text import MIMEText
msg = MIMEMultipart() msg["Subject"] = "Hallo Welt" msg["From"] = "Donald Duck <don@ld.de>" msg["To"] = "Onkel Dagobert <d@gobert.de>"
text = MIMEText("Dies ist meine selbst erstelle E-Mail.") msg.attach(text)
f = open("buch.png") bild = MIMEImage(f.read()) f.close() msg.attach(bild)
print msg.as_string()

Zunächst wird eine Instanz der Klasse MIMEMultipart erzeugt. Diese repräsentiert eine E-Mail, die MIME-kodierte Binärdaten enthalten kann. Wie im vorherigen Beispiel werden Betreff, Absender und Empfänger nach Art eines Dictionarys hinzugefügt.

Danach wird eine Instanz der Klasse MIMEText erzeugt, die den reinen Text der E–Mail enthalten soll. Diese Instanz wird mithilfe der Methode attach an die MIMEMultipart-Instanz angehängt.

Genauso wird mit dem Bild verfahren: Es wird eine Instanz der Klasse MIMEImage erzeugt und mit den Binärdaten des Bildes gefüllt. Danach wird sie mittels attach an die E-Mail angefügt.

Schlussendlich wird die MIMEMultipart-Instanz durch Aufruf der Methode as_string in einen String konvertiert, der so als reine ASCII-E-Mail versendet werden kann. Der angefügte Anhang wird von E-Mail-Programmen als Grafik erkannt und dann dementsprechend präsentiert.

Die Ausgabe des Beispiels sieht in etwa so aus:

Content-Type: multipart/mixed; boundary="===========0094312333==" 
MIME-Version: 1.0 
Subject: Hallo Welt 
From: Donald Duck <don@ld.de> 
To: Onkel Dagobert <d@gobert.de> 
 
--===============0094312333== 
Content-Type: text/plain; charset="us-ascii" 
MIME-Version: 1.0 
Content-Transfer-Encoding: 7bit 
 
Dies ist meine selbst erstelle E-Mail. 
--===============0094312333== 
Content-Type: image/png 
MIME-Version: 1.0 
Content-Transfer-Encoding: base64 
 
iVBORw0KGgoAAAANSUhEUgAAASwAAAD8CAIAAABCVg65AAAACXBIWXMAACcQAAAnE 
B3RJTUUH1wkMERU1+MuwjgAAIABJREFUeNrsfXecJWWV9nPet+rezt2ThzDkqCBLB 
[…] 
--===============0094312333==--

Sie sehen, dass sowohl der Text als auch das Bild in ähnlicher Form kodiert wurden. Die Aufbereitung der beiden Sektionen zum Textteil der E-Mail und zu einem Bild im Anhang erledigt Ihr Mail-Programm. Das mime-Paket bietet auch eine entsprechende Funktionalität an, auf die wir noch zu sprechen kommen werden.

Hier wurden nur MIMEText und MIMEImage besprochen. Im Folgenden sind alle verfügbaren MIME-Datentypen aufgelistet:

  • email.mime.application.MIMEApplication für ausführbare Programme
  • email.mime.audio.MIMEAudio für Sounddateien
  • email.mime.image.MIMEImage für Grafikdateien
  • email.mime.message.MIMEMessage für Message-Instanzen
  • email.mime.image.MIMEText für reinen Text

Beim Instanziieren all dieser Klassen müssen die jeweiligen Binärdaten bzw. der Text, den die entsprechende Instanz enthalten soll, als erster Parameter des Konstruktors übergeben werden. Wichtig ist noch, dass alle hier vorgestellten Klassen von der Basisklasse Message abgeleitet sind, also über die Methoden dieser Basisklasse verfügen.

Internationale Zeichensätze

Bisher wurde besprochen, wie der MIME-Standard dazu verwendet werden kann, Binärdaten im Anhang einer E-Mail zu versenden. Beim Text der E-Mail waren wir aber bislang auf die Zeichen des 7-Bit-ASCII-Standards beschränkt. Die Frage ist, wie ein spezielles Encoding innerhalb einer E-Mail verwendet werden kann. Auch dies ermöglicht der MIME-Standard. Das folgende Beispielprogramm soll eine einfache E-Mail erstellen, deren Text ein Euro-Zeichen enthält.

from email.mime.text import MIMEText
text = u"39,90\u20AC" msg = MIMEText(text.encode("cp1252"), _charset="cp1251") msg["Subject"] = "Hallo Welt" msg["From"] = "Donald Duck <don@ld.de>" msg["To"] = "Onkel Dagobert <d@gobert.de>"
print msg.as_string()

Als Erstes erzeugen wir einen Unicode-String, der das Euro-Zeichen enthält, das nicht im ASCII-Standard enthalten ist. Nachfolgend wird der Unicode-String ins Windows-Encoding cp1252 kodiert und bei der Instanziierung der Klasse MIME Text übergeben. Das verwendete Encoding muss dem Konstruktor ebenfalls über den Parameter _charset bekannt gemacht werden. Der nun folgende Teil des Programms ist bereits von den anderen Beispielen her bekannt.

Der MIME-kodierte Text, den das Beispielprogramm ausgibt, sieht folgendermaßen aus:

Content-Type: text/plain; charset="cp1252" 
MIME-Version: 1.0 
Content-Transfer-Encoding: base64 
Subject: Hallo Welt 
From: Donald Duck <don@ld.de> 
To: Onkel Dagobert <d@gobert.de> 
 
MzksOTCA

Dabei entspricht MzksOTCA der MIME-Kodierung des Texts 39,90€.

Es kann durchaus vorkommen, dass auch Einträge im Header der E-Mail Sonderzeichen enthalten. Solche können mithilfe der Klasse Header kodiert werden:

from email.mime.text import MIMEText 
from email.header import Header 
msg = MIMEText("Hallo Welt") 
msg["Subject"] = Header("39,90\u20AC", "cp1252") 
[…]

Eine E-Mail einlesen

Zum Schluss möchten wir noch ein kurzes Beispiel dazu geben, dass eine abgespeicherte E-Mail auch wieder eingelesen und automatisch zu der bislang besprochenen Klassenstruktur aufbereitet werden kann. Dazu folgendes Beispiel:

import email
mail = """Subject: Hallo Welt From: Donald Duck <don@ld.de> To: Onkel Dagobert <d@gobert.de> Hallo Welt """
msg = email.message_from_string(mail) print msg["From"]

Im Beispielprogramm ist eine E-Mail in Form eines Strings vorhanden und wird durch die Funktion message_from_string eingelesen. Diese Funktion gibt eine vollwertige Message-Instanz zurück, wie die darauf folgende print-Ausgabe beweist:

Donald Duck <don@ld.de>

Alternativ hätte auch die Funktion message_from_file verwendet werden können, um die E-Mail aus einer Datei zu lesen. Dieser Funktion hätten wir dann ein geöffnetes Dateiobjekt übergeben müssen.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.






 <<   zurück
  
  Zum Katalog
Zum Katalog: Python






Python
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Linux






 Linux


Zum Katalog: Ubuntu GNU/Linux






 Ubuntu GNU/Linux


Zum Katalog: Praxisbuch Web 2.0






 Praxisbuch Web 2.0


Zum Katalog: UML 2.0






 UML 2.0


Zum Katalog: Praxisbuch Objektorientierung






 Praxisbuch Objektorientierung


Zum Katalog: Einstieg in SQL






 Einstieg in SQL


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für Fachinformatiker


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo