Mit Python mit einem Gmail-POPerver sprechen

PHPz
Freigeben: 2024-09-08 06:31:43
Original
1234 Leute haben es durchsucht

Talking to a Gmail POPerver with Python

POP ist ein relativ altes Protokoll. Die erste Version wurde 1984 spezifiziert. Die heute noch verwendete Version, POP3, wurde 1996 spezifiziert. Um es auszuprobieren, habe ich eine Verbindung zu einem Gmail-POP3-Server hergestellt.

Der erste Schritt bestand darin, die POP3-Einstellungen nachzuschlagen – mit welchem ​​Server über welchen Port eine Verbindung hergestellt werden soll. Google hat mich hierher geführt, wo ich die folgenden Informationen gefunden habe.

pop.gmail.com

SSL erforderlich: Ja

Port: 995

Es wird erwähnt, dass SSL erforderlich ist. Damit hatte ich vor 25 Jahren, als ich das letzte Mal mit POP herumgespielt habe, noch nichts zu tun. Ich hatte Angst, dass es Kopfschmerzen bereiten würde, aber es stellte sich heraus, dass es überhaupt keine Herausforderung darstellte; Mit ein wenig Hilfe aus den Python-Dokumenten bin ich zu diesem Code gekommen.

import socket
import ssl

hostname = 'pop.gmail.com'
context = ssl.create_default_context()

with socket.create_connection((hostname, 995)) as sock:
    with context.wrap_socket(sock, server_hostname=hostname) as s:
        print(s.version())
Nach dem Login kopieren

Es stellt eine Verbindung her und sagt mir, welche SSL-Version verwendet wird ... oder so. Großer Erfolg! Zeit, ein Gespräch mit dem Server zu beginnen.

In Anlehnung an den offiziellen RFC für POP3 finden Sie hier ein Beispiel für eine POP3-Konversation zwischen einem Client und einem Server/

C: <open connection>
S:    +OK POP3 server ready <1896.697170952@dbc.mtview.ca.us>
C:    USER mrose
S:    +OK mrose is a real hoopy frood
C:    PASS secret
S:    +OK mrose's maildrop has 2 messages (320 octets)
C:    STAT
S:    +OK 2 320
C:    LIST
S:    +OK 2 messages (320 octets)
S:    1 120
S:    2 200
S:    .
C:    RETR 1
S:    +OK 120 octets
S:    <the POP3 server sends message 1>
S:    .
C:    QUIT
S:    +OK dewey POP3 server signing off (maildrop empty)
C:  <close connection>
Nach dem Login kopieren

Das erste, was passiert, ist, dass der Server eine Begrüßung an den Client sendet. Freundlich. Also füge ich Code hinzu, um eine Nachricht vom Server zu empfangen.

Wenn Sie den Empfang von Daten von einem Socket anfordern, müssen Sie eine Puffergröße angeben. In den Dokumenten wird eine Potenz von 2 empfohlen, beispielsweise 4096. Viele Antworten vom Server werden auf einmal eingehen. Manche werden es nicht tun; Manchmal wird eine Nachricht vom Server über mehrere Lesevorgänge hinweg unterbrochen, und der Puffer wird möglicherweise nicht bis zum Maximum gefüllt, selbst wenn noch weitere Nachrichten folgen.

Im Fall von POP3 hängt die Art und Weise, wie man erkennt, ob eine Nachricht eingegangen ist, vollständig davon ab, welche Nachricht eingeht. Meistens sendet der Server eine einzelne Textzeile. (Wie wir später noch einmal sehen werden, verfügen diese über ein Wagenrücklauf- und Zeilenvorschubzeichen am Ende jeder Zeile.) Bestimmte Nachrichten, die eine viel längere Antwort haben könnten, verwenden eine andere Möglichkeit, um anzuzeigen, dass sie fertig sind: einen Punkt in einer einzelnen Zeile von selbst.

import socket
import ssl

hostname = 'pop.gmail.com'
context = ssl.create_default_context()

with socket.create_connection((hostname, 995)) as sock:
    with context.wrap_socket(sock, server_hostname=hostname) as s:
        print(s.version())
        data = s.read(4096)
        print(data)
Nach dem Login kopieren

Laufen Sie noch einmal und wir werden begrüßt. Wieder ein toller Erfolg! Beachten Sie, dass die Zeile mit „rn“ endet – Wagenrücklauf- und Zeilenvorschubzeichen.

Sie müssen der Lesemethode eine Puffergröße übergeben. Es steht dann ein Puffer dieser Größe zum Lesen von Daten vom Server zur Verfügung – es gibt jedoch keine Garantie dafür, wie viele Daten gleichzeitig in den Puffer gelangen. Das bedeutet, dass ein Protokoll auf irgendeine Weise angeben muss, wann eine Nachricht abgeschlossen ist. Es sind zahlreiche Strategien möglich. POP verwendet zwei: Für alle Nachrichten werden Zeilen mit rn beendet. Für eine kurze (einzeilige) Nachricht ist dies alles, was erforderlich ist. Bei mehrzeiligen Antworten zeigt ein Punkt in einer Zeile allein an, dass die Nachricht vollständig ist.

TLSv1.3
b'+OK Gpop ready for requests from 2601:1c0:8301:b590:f408:d66a:3029:16ad dq2mb54750689ivb\r\n'
Nach dem Login kopieren

Jetzt müssen wir anfangen, mit dem Server zu sprechen. Zeit, eine I/O-Schleife (oder O/I-Schleife) zu erstellen; Holen Sie sich einige Benutzereingaben und senden Sie sie an den Server. Hoppla! Ich kann eine Zeichenfolge nicht direkt senden. das gibt mir einen TypeError. Ich muss die Nachricht in Bytes konvertieren. Die Methode string encode() erledigt das (die Standardkodierung von utf-8 funktioniert einwandfrei).

Nur ​​wenn ich es ausführe – ups schon wieder! Es passiert nichts, wenn meine Nachricht an den Server gesendet wird. Weil ich vergessen habe, dass Nachrichten, die vom Client kommen, auch mit rn enden müssen. Eine weitere kleine Änderung gibt uns:

import socket
import ssl

hostname = 'pop.gmail.com'
context = ssl.create_default_context()

with socket.create_connection((hostname, 995)) as sock:
    with context.wrap_socket(sock, server_hostname=hostname) as s:
        print(s.version())
        while True:
            data = s.read(4096)
            print(data)
            msg = input() + "\r\n"
            s.send(msg.encode())
Nach dem Login kopieren

Großartig, jetzt kann ich tatsächlich versuchen, mich einzuloggen!

TLSv1.3
b'+OK Gpop ready for requests from 2601:1c0:8301:b590:f408:d66a:3029:16ad g4mb5147337iow\r\n'
USER grokprogramming
b'+OK send PASS\r\n'
PASS trustno1
b'-ERR [AUTH] Application-specific password required: https://support.google.com/accounts/answer/185833\r\n'
Nach dem Login kopieren

OK, wenn ich diesem Link folge, komme ich zu einer Seite, auf der ich ein anwendungsspezifisches Passwort einrichten kann. Ein potenzieller Stolperstein, auf den ich gestoßen bin: Soweit ich weiß, muss für Ihr Konto die Zwei-Faktor-Authentifizierung aktiviert sein, damit Sie ein anwendungsspezifisches Passwort festlegen können. Warum sollte ich im Jahr unserer Lorde 2024 nicht die Zwei-Faktor-Authentifizierung aktiviert haben? Das kann ich nicht sagen. Das tue ich jetzt.

Ausgerüstet mit einem anwendungsspezifischen Passwort (bitte beachten Sie, dass Sie die Leerzeichen weglassen) kann ich mich anmelden! Dann gebe ich den STAT-Befehl aus, der mir sagt, wie viele Nachrichten ich habe und wie groß sie insgesamt sind. Danach gebe ich den Befehl LIST aus, der eine Liste von Nachrichten mit einer ID und einer Größe für jede einzelne zurückgibt.

TLSv1.3
b'+OK Gpop ready for requests from 2601:1c0:8301:b590:f408:d66a:3029:16ad e18mb76868856iow\r\n'
USER grokprogramming
b'+OK send PASS\r\n'
PASS baygdsgkmihkckrb
b'+OK Welcome.\r\n'
STAT
b'+OK 263 14191565\r\n'
LIST
b'+OK 263 messages (14191565 bytes)\r\n1 2778\r\n2 2947\r\n3 6558\r\n4 9864\r\n5 35997\r\n6 45462\r\n7 45462\r\n8 63894\r\n9 11487\r\n10 74936\r\n11 74925\r\n12 11632\r\n13 32392\r\n14 74997\r\n15 51961\r\n16 15375\r\n17 46513\r\n18 21519\r\n19 15966\r\n20 27258\r\n21 28503\r\n22 35615\r\n23 86353\r\n24 280'

Nach dem Login kopieren

Ich habe einen Fehler im Code festgestellt. Die Antwort für LIST erstreckt sich über mehrere Zeilen und erfordert in diesem Fall mehrere Pufferlesevorgänge. Die gesamte Nachricht endet mit einem Punkt in einer Zeile. Hier habe ich die Nachricht im Wert von einem Puffer erhalten, und jetzt muss ich die Eingabetaste drücken und eine leere Nachricht an den Server senden, damit der Code zur nächsten Iteration der Schleife übergeht und erneut aus dem Puffer liest.

Ich werde den Code so optimieren, dass der Benutzer immer die Möglichkeit hat, erneut aus dem Puffer zu lesen oder nicht. Ich werde auch endlich die vom Server eingehenden Bytes dekodieren, damit der Text schöner dargestellt wird.

import socket
import ssl

hostname = 'pop.gmail.com'
context = ssl.create_default_context()

with socket.create_connection((hostname, 995)) as sock:
    with context.wrap_socket(sock, server_hostname=hostname) as s:
        print(s.version())
        while True:
            data = s.read(4096)
            print(data.decode())
            while input("more? y/[n]: ") == "y":
                data = s.read(4096)
                print(data.decode())
            msg = input("> ") + "\r\n"
            s.send(msg.encode())
Nach dem Login kopieren

Und hier ist eine vollständige Sitzung, einschließlich des Abrufens einer E-Mail und des Sendens der Trennungsnachricht.

> USER grokprogramming
+OK send PASS

more? y/[n]: 
> PASS trustno1
+OK Welcome.

more? y/[n]: 
> STAT
+OK 263 14191565

more? y/[n]: 
> LIST
+OK 263 messages (14191565 bytes)
1 2778
2 2947
3 6558
<...>
260 41300
261 114059
262 174321
263 39206
.

more? y/[n]: 
> RETR 1
+OK message follows
MIME-Version: 1.0
Received: by 10.76.81.230; Thu, 28 Jun 2012 20:21:50 -0700 (PDT)
Date: Thu, 28 Jun 2012 20:21:50 -0700
Message-ID: <CADBp03TWFOKcTOaK_0P7VV2GB+TZsoSd_W4G5nZKKs7pdk6cWQ@mail.gmail.com>
Subject: Customize Gmail with colors and themes
From: Gmail Team <mail-noreply@google.com>
To: Grok Programming <grokprogramming@gmail.com>
Content-Type: multipart/alternative; boundary=e0cb4e385592f8025004c393f2b4

--e0cb4e385592f8025004c393f2b4
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

To spice up your inbox with colors and themes, check out the Themes tab
under Settings.
       Customize Gmail =BB <https://mail.google.com/mail/#settings/themes>

Enjoy!

- The Gmail Team
[image: Themes thumbnails]

Please note that Themes are not available if you're using Internet Explorer
6.0. To take advantage of the latest Gmail features, please upgrade to a
fully supported
browser<http://support.google.com/mail/bin/answer.py?answer=3D6557&hl=3Den&=
utm_source=3Dwel-eml&utm_medium=3Deml&utm_campaign=3Den>
..

--e0cb4e385592f8025004c393f2b4
Content-Type: text/html; charset=ISO-8859-1

more? y/[n]: y

<html>
<font face="Arial, Helvetica, sans-serif">
<p>To spice up your inbox with colors and themes, check out the Themes tab
under Settings.</p>

<table cellpadding="0" cellspacing="0">
  <col style="width: 1px;"/>
  <col/>
  <col style="width: 1px;"/>
  <tr>
    <td></td>
    <td height="1px" style="background-color: #ddd"></td>
    <td></td>
  </tr>
  <tr>
    <td style="background-color: #ddd"></td>
    <td background="https://mail.google.com/mail/images/welcome-button-background.png"
        style="background-color: #ddd; background-repeat: repeat-x;
            padding: 10px; font-size: larger">
          <a href="https://mail.google.com/mail/#settings/themes"
            style="font-weight: bold; color: #000; text-decoration: none;
            display: block;">
      Customize Gmail &#187;</a>
    </td>
    <td style="ba
more? y/[n]: y
ckground-color: #ddd"></td>
  </tr>
 <tr>
    <td></td>
    <td height="1px" style="background-color: #ddd"></td>
    <td></td>
  </tr>
</table>

<p>Enjoy!</p>

<p>- The Gmail Team</p>

<img width="398" height="256" src="https://mail.google.com/mail/images/gmail_themes_2.png" alt="Themes thumbnails" />

<p><font size="-2" color="#999">Please note that Themes are not available if
you're using Internet Explorer 6.0. To take advantage of the latest Gmail
features, please
<a href="http://support.google.com/mail/bin/answer.py?answer=6557&hl=en&utm_source=wel-eml&utm_medium=eml&utm_campaign=en"><font color="#999">
upgrade to a fully supported browser</font></a>.</font></p>

</font>
</html>

--e0cb4e385592f8025004c393f2b4--
.

more? y/[n]: 
> QUIT
+OK Farewell.

more? y/[n]: 
> 
Nach dem Login kopieren

Yet another great success! I was able to log in to the POP3 server and retrieve a message. The script in its current state is pretty flexible, but it requires a lot of work from the user. I'll make a few final tweaks to make interacting with the POP3 server a little easier: if the user starts a message to the server with a "!" it will be stripped out, but the script will read in data from the server until it gets to a period on a line by itself -- in other words, for commands with long responses. No "!" and the script will read in a single line, looking for the \r\n characters.

import socket
import ssl

hostname = 'pop.gmail.com'
context = ssl.create_default_context()

def read_until(s, eom):
    # read into the buffer at least once
    data = s.read(4096)
    # continue reading until end of message
    while data[-len(eom):] != eom:
        data += s.read(4096)
    # return incoming bytes decoded to a string
    return data.decode()

def read_single_line(s):
    return read_until(s, b"\r\n")

def read_muli_line(s):
    return read_until(s, b"\r\n.\r\n")

with socket.create_connection((hostname, 995)) as sock:
    with context.wrap_socket(sock, server_hostname=hostname) as s:
        print(s.version())
        print(read_single_line(s))
        msg = input("> ")
        # empty msg will close connection
        while msg != "":
            if msg[0] == "!":
                msg = msg[1:]
                long = True
            else:
                long = False
            msg += "\r\n"
            s.send(msg.encode())
            if long:
                print(read_muli_line(s))
            else:
                print(read_single_line(s))
            msg = input("> ")
        s.close()
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonMit Python mit einem Gmail-POPerver sprechen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage