it-swarm.com.de

So senden Sie eine E-Mail mit Python

Dieser Code funktioniert und schickt mir eine E-Mail: 

import smtplib
#SERVER = "localhost"

FROM = '[email protected]'

TO = ["[email protected]"] # must be a list

SUBJECT = "Hello!"

TEXT = "This message was sent with Python's smtplib."

# Prepare actual message

message = """\
From: %s
To: %s
Subject: %s

%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)

# Send the mail

server = smtplib.SMTP('myserver')
server.sendmail(FROM, TO, message)
server.quit()

Wenn ich jedoch versuche, es in eine Funktion wie diese einzuwickeln:

def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
    import smtplib
    """this is some test documentation in the function"""
    message = """\
        From: %s
        To: %s
        Subject: %s
        %s
        """ % (FROM, ", ".join(TO), SUBJECT, TEXT)
    # Send the mail
    server = smtplib.SMTP(SERVER)
    server.sendmail(FROM, TO, message)
    server.quit()

und nenne es folgende Fehler: 

 Traceback (most recent call last):
  File "C:/Python31/mailtest1.py", line 8, in <module>
    sendmail.sendMail(sender,recipients,subject,body,server)
  File "C:/Python31\sendmail.py", line 13, in sendMail
    server.sendmail(FROM, TO, message)
  File "C:\Python31\lib\smtplib.py", line 720, in sendmail
    self.rset()
  File "C:\Python31\lib\smtplib.py", line 444, in rset
    return self.docmd("rset")
  File "C:\Python31\lib\smtplib.py", line 368, in docmd
    return self.getreply()
  File "C:\Python31\lib\smtplib.py", line 345, in getreply
    raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed

Kann mir jemand helfen zu verstehen warum? 

135
cloud311

Ich empfehle Ihnen, die Standardpakete email und smtplib zusammen zu verwenden, um E-Mails zu senden. Sehen Sie sich das folgende Beispiel an (Wiedergabe aus der Python-Dokumentation ). Wenn Sie diesem Ansatz folgen, ist die "einfache" Aufgabe in der Tat einfach, und die komplexeren Aufgaben (z. B. das Anhängen von binären Objekten oder das Senden von einfachen/HTML-Multipart-Nachrichten) werden sehr schnell ausgeführt.

# Import smtplib for the actual sending function
import smtplib

# Import the email modules we'll need
from email.mime.text import MIMEText

# Open a plain text file for reading.  For this example, assume that
# the text file contains only ASCII characters.
with open(textfile, 'rb') as fp:
    # Create a text/plain message
    msg = MIMEText(fp.read())

# me == the sender's email address
# you == the recipient's email address
msg['Subject'] = 'The contents of %s' % textfile
msg['From'] = me
msg['To'] = you

# Send the message via our own SMTP server, but don't include the
# envelope header.
s = smtplib.SMTP('localhost')
s.sendmail(me, [you], msg.as_string())
s.quit()

Um E-Mails an mehrere Ziele zu senden, können Sie auch dem Beispiel in der Python-Dokumentation folgen:

# Import smtplib for the actual sending function
import smtplib

# Here are the email package modules we'll need
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart

# Create the container (outer) email message.
msg = MIMEMultipart()
msg['Subject'] = 'Our family reunion'
# me == the sender's email address
# family = the list of all recipients' email addresses
msg['From'] = me
msg['To'] = ', '.join(family)
msg.preamble = 'Our family reunion'

# Assume we know that the image files are all in PNG format
for file in pngfiles:
    # Open the files in binary mode.  Let the MIMEImage class automatically
    # guess the specific image type.
    with open(file, 'rb') as fp:
        img = MIMEImage(fp.read())
    msg.attach(img)

# Send the email via our own SMTP server.
s = smtplib.SMTP('localhost')
s.sendmail(me, family, msg.as_string())
s.quit()

Wie Sie sehen können, muss der Header To im Objekt MIMEText eine Zeichenfolge sein, die aus E-Mail-Adressen besteht, die durch Kommas getrennt sind. Andererseits muss das zweite Argument der sendmail-Funktion eine Liste von Strings sein (jeder String ist eine E-Mail-Adresse).

Wenn Sie also drei E-Mail-Adressen haben: [email protected], [email protected] und [email protected], können Sie Folgendes tun (offensichtliche Abschnitte werden weggelassen):

to = ["[email protected]", "[email protected]", "[email protected]"]
msg['To'] = ",".join(to)
s.sendmail(me, to, msg.as_string())

der "","".join(to)-Teil erstellt eine einzelne Zeichenfolge aus der Liste, die durch Kommas getrennt ist.

Aus Ihren Fragen stelle ich fest, dass Sie das Python-Tutorial nicht durchlaufen haben - es ist ein MUSS, wenn Sie irgendwo in Python hin wollen - die Dokumentation ist für die Standardbibliothek meist hervorragend.

164
Escualo

Nun, Sie möchten eine Antwort haben, die aktuell und modern ist.

Hier ist meine Antwort:

Wenn ich in Python mailen muss, benutze ich die mailgun API, die viele Kopfschmerzen beim Aussenden von Mails verursacht. Sie haben eine wunderbare App/API, mit der Sie 10.000 E-Mails pro Monat kostenlos senden können.

Das Versenden einer E-Mail würde folgendermaßen aussehen:

def send_simple_message():
    return requests.post(
        "https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages",
        auth=("api", "YOUR_API_KEY"),
        data={"from": "Excited User <[email protected]_DOMAIN_NAME>",
              "to": ["[email protected]", "[email protected]_DOMAIN_NAME"],
              "subject": "Hello",
              "text": "Testing some Mailgun awesomness!"})

Sie können auch Ereignisse und vieles mehr verfolgen, siehe die Kurzanleitung .

Ich hoffe du findest das nützlich!

58
Dennis Decoene

Ich möchte Ihnen gerne beim Versenden von E-Mails helfen, indem ich das yagmail-Paket berate (ich bin der Betreuer, tut mir leid für die Werbung, aber ich glaube, es kann wirklich helfen!) 

Der ganze Code für Sie wäre:

import yagmail
yag = yagmail.SMTP(FROM, 'pass')
yag.send(TO, SUBJECT, TEXT)

Beachten Sie, dass ich für alle Argumente Standardwerte zur Verfügung stelle. Wenn Sie beispielsweise an sich selbst senden möchten, können Sie TO weglassen. Wenn Sie keinen Betreff wünschen, können Sie ihn auch weglassen.

Außerdem soll das Anfügen von HTML-Code oder Bildern (und anderen Dateien) sehr einfach gestaltet werden.

Wo Sie Inhalte ablegen, können Sie Folgendes tun:

contents = ['Body text, and here is an embedded image:', 'http://somedomain/image.png',
            'You can also find an audio file attached.', '/local/path/song.mp3']

Wow, wie einfach ist das Senden von Anhängen! Dies würde etwa 20 Zeilen ohne Yagmail dauern;)

Wenn Sie es einmal einrichten, müssen Sie das Kennwort niemals erneut eingeben (und es sicher aufbewahren). In Ihrem Fall können Sie Folgendes tun:

import yagmail
yagmail.SMTP().send(contents = contents)

das ist viel prägnanter!

Ich möchte Sie einladen, sich den github anzusehen oder ihn direkt mit pip install yagmail zu installieren.

34
PascalVKooten

Es gibt ein Einrückungsproblem. Der folgende Code wird funktionieren:

import textwrap

def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
    import smtplib
    """this is some test documentation in the function"""
    message = textwrap.dedent("""\
        From: %s
        To: %s
        Subject: %s
        %s
        """ % (FROM, ", ".join(TO), SUBJECT, TEXT))
    # Send the mail
    server = smtplib.SMTP(SERVER)
    server.sendmail(FROM, TO, message)
    server.quit()

14
Zeeshan

Versuche dies:

def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
    import smtplib
    """this is some test documentation in the function"""
    message = """\
        From: %s
        To: %s
        Subject: %s
        %s
        """ % (FROM, ", ".join(TO), SUBJECT, TEXT)
    # Send the mail
    server = smtplib.SMTP(SERVER)
    "New part"
    server.starttls()
    server.login('username', 'password')
    server.sendmail(FROM, TO, message)
    server.quit()

Es funktioniert für smtp.gmail.com

8
Theoremiser

Während Sie den Code in der Funktion einrücken (was in Ordnung ist), haben Sie auch die Zeilen der unformatierten Nachrichtenzeichenfolge eingerückt. Führende Leerzeichen implizieren jedoch das Falten (Verketten) der Kopfzeilen, wie in den Abschnitten 2.2.3 und 3.2.3 von RFC 2822 - Internet Message Format beschrieben.

Jedes Headerfeld ist logisch eine einzelne Zeichenzeile mit der Feldname, der Doppelpunkt und der Feldkörper. Zur Bequemlichkeit Um jedoch mit den 998/78 Zeicheneinschränkungen pro Zeile umzugehen, muss Der Feldhauptteil eines Kopfzeilenfelds kann in ein Vielfaches aufgeteilt werden Liniendarstellung; Dies wird als "Faltung" bezeichnet.

In der Funktionsform Ihres sendmail-Aufrufs beginnen alle Zeilen mit Leerzeichen, werden also "entfaltet" (verkettet) und Sie versuchen zu senden

From: [email protected]    To: [email protected]    Subject: Hello!    This message was sent with Python's smtplib.

Anders als unser Kopf vermuten lässt, wird smtplib die Header To: und Subject: nicht mehr verstehen, da diese Namen nur am Anfang einer Zeile erkannt werden. Stattdessen geht smtplib von einer sehr langen Absender-E-Mail-Adresse aus: 

[email protected]    To: [email protected]    Subject: Hello!    This message was sent with Python's smtplib.

Das wird nicht funktionieren und so kommt deine Ausnahme.

Die Lösung ist einfach: Behalten Sie die message-Zeichenfolge wie zuvor bei. Dies kann durch eine Funktion (wie von Zeeshan vorgeschlagen) oder direkt im Quellcode ausgeführt werden:

import smtplib

def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
    """this is some test documentation in the function"""
    message = """\
From: %s
To: %s
Subject: %s

%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
    # Send the mail
    server = smtplib.SMTP(SERVER)
    server.sendmail(FROM, TO, message)
    server.quit()

Nun entfällt die Entfaltung und Sie senden

From: [email protected]
To: [email protected]
Subject: Hello!

This message was sent with Python's smtplib.

was ist das, was funktioniert und was mit Ihrem alten Code getan wurde.

Beachten Sie, dass ich auch die leere Zeile zwischen Kopfzeilen und Rumpf beibehalten habe, um Abschnitt 3.5 von RFC (der erforderlich ist) aufzunehmen, und das Include außerhalb der Funktion gemäß der Python-Stilanleitung PEP-0008 ( was optional ist).

4
flaschbier

Wahrscheinlich werden Ihre Nachrichten mit Tabs versehen. Drucken Sie die Nachricht aus, bevor Sie sie an sendMail übergeben.

3
Nick ODell

Stellen Sie sicher, dass Sie sowohl dem Sender als auch dem Empfänger die Berechtigung zum Senden von E-Mails und Empfangen von E-Mails von unbekannten Quellen (externe Quellen) im E-Mail-Konto erteilt haben.

import smtplib

#Ports 465 and 587 are intended for email client to email server communication - sending email
server = smtplib.SMTP('smtp.gmail.com', 587)

#starttls() is a way to take an existing insecure connection and upgrade it to a secure connection using SSL/TLS.
server.starttls()

#Next, log in to the server
server.login("#email", "#password")

msg = "Hello! This Message was sent by the help of Python"

#Send the mail
server.sendmail("#Sender", "#Reciever", msg)

 enter image description here

2
Devanand Sharma

Hier ist ein Beispiel für Python 3.x, viel einfacher als 2.x:

import smtplib
from email.message import EmailMessage
def send_mail(to_email, subject, message, server='smtp.example.cn',
              from_email='[email protected]'):
    # import smtplib
    msg = EmailMessage()
    msg['Subject'] = subject
    msg['From'] = from_email
    msg['To'] = ', '.join(to_email)
    msg.set_content(message)
    print(msg)
    server = smtplib.SMTP(server)
    server.set_debuglevel(1)
    server.login(from_email, 'password')  # user & password
    server.send_message(msg)
    server.quit()
    print('successfully sent the mail.')

rufen Sie diese Funktion auf:

send_mail(to_email=['[email protected]', '[email protected]'],
          subject='hello', message='Your analysis has done!')

unten darf nur für chinesische Benutzer:

Wenn Sie 126/163 verwenden, müssen Sie "端 授权 密码" wie folgt einstellen:

enter image description here

ref: https://stackoverflow.com/a/41470149/2803344https://docs.python.org/3/library/email.examples.html#email-examples

1
Belter

Was Ihren Code anbelangt, so scheint dies nichts Grundlegendes zu sein, außer es ist unklar, wie Sie diese Funktion tatsächlich aufrufen. Alles, was ich mir vorstellen kann, ist, dass, wenn Ihr Server nicht reagiert, Sie diesen SMTPServerDisconnected-Fehler erhalten. Wenn Sie die getreply () - Funktion in smtplib (Auszug unten) nachschlagen, erhalten Sie eine Idee.

def getreply(self):
    """Get a reply from the server.

    Returns a Tuple consisting of:

      - server response code (e.g. '250', or such, if all goes well)
        Note: returns -1 if it can't read response code.

      - server response string corresponding to response code (multiline
        responses are converted to a single, multiline string).

    Raises SMTPServerDisconnected if end-of-file is reached.
    """

ein Beispiel finden Sie unter https://github.com/rreddy80/sendEmails/blob/master/sendEmailAttachments.py , das auch einen Funktionsaufruf zum Senden einer E-Mail verwendet, wenn Sie dies versuchen (DRY-Ansatz) ).

0
rreddy

Ich dachte, ich würde meine zwei Teile hier einsetzen, seit ich herausgefunden habe, wie das funktioniert. 

Es scheint, dass Sie nicht den Port in den SERVER-Verbindungseinstellungen angegeben haben. Dies hat mich etwas beeinträchtigt, als ich versuchte, eine Verbindung zu meinem SMTP-Server herzustellen, der nicht den Standardport verwendet: 25. 

Gemäß den smtplib.SMTP-Dokumenten sollte Ihre Ehlo- oder Helo-Anfrage/-Antwort automatisch erledigt werden, so dass Sie sich keine Sorgen machen müssen (aber möglicherweise etwas zur Bestätigung, wenn alles andere fehlschlägt).

Eine andere Frage ist, ob Sie SMTP-Verbindungen auf Ihrem SMTP-Server selbst zugelassen haben. Für einige Sites wie GMAIL und ZOHO müssen Sie tatsächlich die IMAP-Verbindungen innerhalb des E-Mail-Kontos aktivieren. Ihr Mailserver lässt möglicherweise keine SMTP-Verbindungen zu, die möglicherweise nicht von 'localhost' stammen. Etwas zum Nachsehen. 

Die letzte Sache ist, Sie möchten vielleicht versuchen, die Verbindung über TLS herzustellen. Die meisten Server erfordern jetzt diese Art der Authentifizierung.

Sie werden sehen, dass ich zwei TO-Felder in meine E-Mail eingefügt habe. Die Einträge im msg ['TO'] - und 'msg [' FROM '] - Wörterbuch ermöglichen die Anzeige der korrekten Informationen in den Kopfzeilen der E-Mail selbst, die Sie am empfangenden Ende der E-Mail in den To/From-Feldern sehen Es ist sogar möglich, ein Feld "Antwort an" hier hinzuzufügen. Die Felder "TO" und "FROM" selbst sind für den Server erforderlich. Ich weiß, dass einige E-Mail-Server E-Mails abgelehnt haben, wenn sie nicht über die richtigen E-Mail-Header verfügen. 

Dies ist der Code, den ich in einer Funktion verwendet habe, mit dem ich den Inhalt einer * .txt-Datei mit meinem lokalen Computer und einem Remote-SMTP-Server (ZOHO wie gezeigt) per E-Mail versenden kann: 

def emailResults(folder, filename):

    # body of the message
    doc = folder + filename + '.txt'
    with open(doc, 'r') as readText:
        msg = MIMEText(readText.read())

    # headers
    TO = '[email protected]'
    msg['To'] = TO
    FROM = '[email protected]'
    msg['From'] = FROM
    msg['Subject'] = 'email subject |' + filename

    # SMTP
    send = smtplib.SMTP('smtp.zoho.com', 587)
    send.starttls()
    send.login('[email protected]', 'password')
    send.sendmail(FROM, TO, msg.as_string())
    send.quit()
0
ntk4