Senden von E-Mails aus Python über SMTP

118

Ich verwende die folgende Methode, um E-Mails von Python über SMTP zu senden. Ist es die richtige Methode oder fehlen mir Fallstricke?

from smtplib import SMTP
import datetime

debuglevel = 0

smtp = SMTP()
smtp.set_debuglevel(debuglevel)
smtp.connect('YOUR.MAIL.SERVER', 26)
smtp.login('USERNAME@DOMAIN', 'PASSWORD')

from_addr = "John Doe <[email protected]>"
to_addr = "[email protected]"

subj = "hello"
date = datetime.datetime.now().strftime( "%d/%m/%Y %H:%M" )

message_text = "Hello\nThis is a mail from your server\n\nBye\n"

msg = "From: %s\nTo: %s\nSubject: %s\nDate: %s\n\n%s" 
        % ( from_addr, to_addr, subj, date, message_text )

smtp.sendmail(from_addr, to_addr, msg)
smtp.quit()
Eli Bendersky
quelle
2
Stellen Sie sicher, dass Datum und Uhrzeit korrekt sind. Ich fand die folgende Funktion sehr nützlich, die Ihnen einen perfekt formatierten Wert für den Datums
BastiBen
Hier ist ein Codebeispiel, das zeigt, wie Bilder inline gesendet werden (plus E-Mail mit HTML- und Nur-Text-Teilen) . Außerdem wird gezeigt, wie SSL-Parameter in alten Python-Versionen konfiguriert werden.
JFS
2
Beachten Sie, dass es Wrapper-Bibliotheken gibt, die das Versenden von E-Mails (z. B. yagmail )
erheblich

Antworten:

111

Das Skript, das ich benutze, ist ziemlich ähnlich; Ich poste es hier als Beispiel für die Verwendung der E-Mail. * -Module zum Generieren von MIME-Nachrichten. So kann dieses Skript leicht geändert werden, um Bilder usw. anzuhängen.

Ich verlasse mich auf meinen ISP, um den Datums- / Uhrzeit-Header hinzuzufügen.

Mein ISP verlangt, dass ich zum Senden von E-Mails eine sichere SMTP-Verbindung verwende. Ich verlasse mich auf das SMTPLIB-Modul (herunterladbar unter http://www1.cs.columbia.edu/~db2501/ssmtplib.py ).

Wie in Ihrem Skript sind der Benutzername und das Kennwort (siehe Dummy-Werte unten), die zur Authentifizierung auf dem SMTP-Server verwendet werden, in der Quelle im Klartext angegeben. Dies ist eine Sicherheitsschwäche. Die beste Alternative hängt jedoch davon ab, wie sorgfältig Sie diese schützen müssen (wollen?).

=======================================

#! /usr/local/bin/python


SMTPserver = 'smtp.att.yahoo.com'
sender =     'me@my_email_domain.net'
destination = ['recipient@her_email_domain.com']

USERNAME = "USER_NAME_FOR_INTERNET_SERVICE_PROVIDER"
PASSWORD = "PASSWORD_INTERNET_SERVICE_PROVIDER"

# typical values for text_subtype are plain, html, xml
text_subtype = 'plain'


content="""\
Test message
"""

subject="Sent from Python"

import sys
import os
import re

from smtplib import SMTP_SSL as SMTP       # this invokes the secure SMTP protocol (port 465, uses SSL)
# from smtplib import SMTP                  # use this for standard SMTP protocol   (port 25, no encryption)

# old version
# from email.MIMEText import MIMEText
from email.mime.text import MIMEText

try:
    msg = MIMEText(content, text_subtype)
    msg['Subject']=       subject
    msg['From']   = sender # some SMTP servers will do this automatically, not all

    conn = SMTP(SMTPserver)
    conn.set_debuglevel(False)
    conn.login(USERNAME, PASSWORD)
    try:
        conn.sendmail(sender, destination, msg.as_string())
    finally:
        conn.quit()

except:
    sys.exit( "mail failed; %s" % "CUSTOM_ERROR" ) # give an error message
Vincent Marchetti
quelle
1
@ Vincent: Mail fehlgeschlagen; Das Objekt 'module' hat kein Attribut 'SSLFakeSocket' - mit Google Mail :(
RadiantHex
Dies klingt nach einem Versions- oder Importproblem, um es aufzuspüren: Welche Python-Version verwenden Sie? - Müssen Sie über SSL eine Verbindung zu Ihrem SMTP-Server herstellen (und wenn ja, importieren Sie ssmtplib wie oben)? Können Sie smtplib direkt aus Python Interactive importieren? Wenn ja, ist eine smtplib.SSLFakeSocket-Klasse definiert? Hoffe ich kann helfen
Vincent Marchetti
2
Verwenden Sie smtplib.SMTP_SSL (Standard in den neuesten Versionen von Python), um die Verbindung anstelle von ssmtplib.STMP_SSL (Modul eines Drittanbieters, wie oben angegeben) herzustellen. Beachten Sie, dass das Standardmodul mit einem einzelnen 's' beginnt. Das hat bei mir funktioniert.
Julio Gorgé
2
ersetzen from ssmtplib import SMTP_SSL as SMTPdurch from smtplib import SMTP_SSL as SMTP, und dieses Beispiel würde aus der Standard-Python-Bibliothek funktionieren.
Adam Matan
9
Hinzufügen msg['To'] = ','.join(destination), sonst wird das Ziel nicht in Google Mail angezeigt
Taha Jahangir
88

Die Methode, die ich normalerweise benutze ... nicht viel anders, aber ein bisschen

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText

msg = MIMEMultipart()
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'
msg['Subject'] = 'simple email in python'
message = 'here is the email'
msg.attach(MIMEText(message))

mailserver = smtplib.SMTP('smtp.gmail.com',587)
# identify ourselves to smtp gmail client
mailserver.ehlo()
# secure our email with tls encryption
mailserver.starttls()
# re-identify ourselves as an encrypted connection
mailserver.ehlo()
mailserver.login('[email protected]', 'mypassword')

mailserver.sendmail('[email protected]','[email protected]',msg.as_string())

mailserver.quit()

Das ist es

madman2890
quelle
Wenn Sie die Bestätigung in zwei Schritten verwenden, müssen Sie zuerst ein App-spezifisches Passwort erstellen und Ihr normales Passwort durch dieses ersetzen. Siehe Anmelden mit App-Passwörtern
Suzana
2
Ich stimme zu, dies ist die beste Antwort und sollte akzeptiert werden. Derjenige, der tatsächlich akzeptiert wird, ist minderwertig.
HelloWorld
6
Verwenden Sie für Python3:from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText
Art
21

Auch wenn Sie SMTP-Authentifizierung mit TLS im Gegensatz zu SSL durchführen möchten, müssen Sie nur den Port ändern (verwenden Sie 587) und smtp.starttls () ausführen. Das hat bei mir funktioniert:

...
smtp.connect('YOUR.MAIL.SERVER', 587)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
smtp.login('USERNAME@DOMAIN', 'PASSWORD')
...

quelle
6

Das wichtigste Problem, das ich sehe, ist, dass Sie keine Fehler behandeln: .login () und .sendmail () haben beide Ausnahmen dokumentiert, die sie auslösen können, und es scheint, dass .connect () eine Möglichkeit haben muss, dies anzuzeigen Verbindung nicht möglich - wahrscheinlich eine Ausnahme, die vom zugrunde liegenden Socket-Code ausgelöst wird.

pjz
quelle
6

Stellen Sie sicher, dass keine Firewalls SMTP blockieren. Als ich zum ersten Mal versuchte, eine E-Mail zu senden, wurde diese sowohl von der Windows-Firewall als auch von McAfee blockiert. Es dauerte ewig, bis beide gefunden wurden.

Mark Ransom
quelle
6

Was ist damit?

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(SERVER)
server.sendmail(FROM, TO, message)
server.quit()
Satish
quelle
4

Der folgende Code funktioniert gut für mich:

import smtplib

to = '[email protected]'
gmail_user = '[email protected]'
gmail_pwd = 'yourpassword'
smtpserver = smtplib.SMTP("smtp.gmail.com",587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo() # extra characters to permit edit
smtpserver.login(gmail_user, gmail_pwd)
header = 'To:' + to + '\n' + 'From: ' + gmail_user + '\n' + 'Subject:testing \n'
print header
msg = header + '\n this is test msg from mkyong.com \n\n'
smtpserver.sendmail(gmail_user, to, msg)
print 'done!'
smtpserver.quit()

Ref: http://www.mkyong.com/python/how-do-send-email-in-python-via-smtplib/

Abdul Majeed
quelle
1
Flask hat ein Framework für E-Mails: aus flask.ext.mail Mail importieren. Ich behebe das Problem und dachte, ich würde zum Python-Code zurückkehren, um zu sehen, ob ich etwas zum Laufen bringen könnte. Ich mochte diese Antwort, weil es nackte Knochen waren. Oh ja, und es hat funktioniert!
Achtung: Die vorherige Version der Antwort enthielt die Zeile: smtpserver.close()Es muss sein : smtpserver.quit(), weil close()die TLS-Verbindung nicht richtig beendet wird! close()wird während aufgerufen quit().
Aronadaal
Hallo, ich habe Probleme beim Ausführen der obigen Befehle. wenn ich smtpserver.starttls () verwenden, ich eine SMTP - Fehler "SMTPServerDisconnected: Verbindung unerwartet geschlossen: [Errno 10054]" erhalten .. in berichtet stackoverflow.com/questions/46094175/...
fazkan
3

Sie sollten sicherstellen, dass Sie das Datum im richtigen Format formatieren - RFC2822 .

Douglas Leeder
quelle
3

Der Beispielcode, den ich zum Senden von E-Mails über SMTP verwendet habe.

import smtplib, ssl

smtp_server = "smtp.gmail.com"
port = 587  # For starttls
sender_email = "sender@email"
receiver_email = "receiver@email"
password = "<your password here>"
message = """ Subject: Hi there

This message is sent from Python."""


# Create a secure SSL context
context = ssl.create_default_context()

# Try to log in to server and send email
server = smtplib.SMTP(smtp_server,port)

try:
    server.ehlo() # Can be omitted
    server.starttls(context=context) # Secure the connection
    server.ehlo() # Can be omitted
    server.login(sender_email, password)
    server.sendmail(sender_email, receiver_email, message)
except Exception as e:
    # Print any error messages to stdout
    print(e)
finally:
    server.quit()
Hariharan AR
quelle
2

Sehen Sie all diese langen Antworten? Bitte erlauben Sie mir, mich selbst zu fördern, indem Sie alles in ein paar Zeilen tun.

Importieren und verbinden:

import yagmail
yag = yagmail.SMTP('[email protected]', host = 'YOUR.MAIL.SERVER', port = 26)

Dann ist es nur ein Einzeiler:

yag.send('[email protected]', 'hello', 'Hello\nThis is a mail from your server\n\nBye\n')

Es wird tatsächlich geschlossen, wenn es außerhalb des Gültigkeitsbereichs liegt (oder manuell geschlossen werden kann). Außerdem können Sie Ihren Benutzernamen so in Ihrem Schlüsselbund registrieren, dass Sie Ihr Passwort nicht in Ihr Skript schreiben müssen (es hat mich vor dem Schreiben wirklich gestört yagmail!).

Informationen zu Paket / Installation, Tipps und Tricks finden Sie unter git oder pip , die sowohl für Python 2 als auch für Python 3 verfügbar sind.

PascalVKooten
quelle
@PascalvKoolen Ich habe yagmail installiert und versucht, eine Verbindung herzustellen, indem ich meine E-Mail-ID und mein Passwort angegeben habe. aber es gab mir einen Authentifizierungsfehler
fazkan
0

das kannst du so machen

import smtplib
from email.mime.text import MIMEText
from email.header import Header


server = smtplib.SMTP('mail.servername.com', 25)
server.ehlo()
server.starttls()

server.login('username', 'password')
from = '[email protected]'
to = '[email protected]'
body = 'That A Message For My Girl Friend For tell Him If We will go to eat Something This Nigth'
subject = 'Invite to A Diner'
msg = MIMEText(body,'plain','utf-8')
msg['Subject'] = Header(subject, 'utf-8')
msg['From'] = Header(from, 'utf-8')
msg['To'] = Header(to, 'utf-8')
message = msg.as_string()
server.sendmail(from, to, message)
Skiller Dz
quelle
0

Hier ist ein Arbeitsbeispiel für Python 3.x.

#!/usr/bin/env python3

from email.message import EmailMessage
from getpass import getpass
from smtplib import SMTP_SSL
from sys import exit

smtp_server = 'smtp.gmail.com'
username = '[email protected]'
password = getpass('Enter Gmail password: ')

sender = '[email protected]'
destination = '[email protected]'
subject = 'Sent from Python 3.x'
content = 'Hello! This was sent to you via Python 3.x!'

# Create a text/plain message
msg = EmailMessage()
msg.set_content(content)

msg['Subject'] = subject
msg['From'] = sender
msg['To'] = destination

try:
    s = SMTP_SSL(smtp_server)
    s.login(username, password)
    try:
        s.send_message(msg)
    finally:
        s.quit()

except Exception as E:
    exit('Mail failed: {}'.format(str(E)))
Kennzeichen
quelle
0

Anhand dieses Beispiels habe ich folgende Funktion gemacht:

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

def send_email(host, port, user, pwd, recipients, subject, body, html=None, from_=None):
    """ copied and adapted from
        /programming/10147455/how-to-send-an-email-with-gmail-as-provider-using-python#12424439
    returns None if all ok, but if problem then returns exception object
    """

    PORT_LIST = (25, 587, 465)

    FROM = from_ if from_ else user 
    TO = recipients if isinstance(recipients, (list, tuple)) else [recipients]
    SUBJECT = subject
    TEXT = body.encode("utf8") if isinstance(body, unicode) else body
    HTML = html.encode("utf8") if isinstance(html, unicode) else html

    if not html:
        # Prepare actual message
        message = """From: %s\nTo: %s\nSubject: %s\n\n%s
        """ % (FROM, ", ".join(TO), SUBJECT, TEXT)
    else:
                # /programming/882712/sending-html-email-using-python#882770
        msg = MIMEMultipart('alternative')
        msg['Subject'] = SUBJECT
        msg['From'] = FROM
        msg['To'] = ", ".join(TO)

        # Record the MIME types of both parts - text/plain and text/html.
        # utf-8 -> /programming/5910104/python-how-to-send-utf-8-e-mail#5910530
        part1 = MIMEText(TEXT, 'plain', "utf-8")
        part2 = MIMEText(HTML, 'html', "utf-8")

        # Attach parts into message container.
        # According to RFC 2046, the last part of a multipart message, in this case
        # the HTML message, is best and preferred.
        msg.attach(part1)
        msg.attach(part2)

        message = msg.as_string()


    try:
        if port not in PORT_LIST: 
            raise Exception("Port %s not one of %s" % (port, PORT_LIST))

        if port in (465,):
            server = smtplib.SMTP_SSL(host, port)
        else:
            server = smtplib.SMTP(host, port)

        # optional
        server.ehlo()

        if port in (587,): 
            server.starttls()

        server.login(user, pwd)
        server.sendmail(FROM, TO, message)
        server.close()
        # logger.info("SENT_EMAIL to %s: %s" % (recipients, subject))
    except Exception, ex:
        return ex

    return None

Wenn Sie nur übergeben, bodywird eine einfache Textmail gesendet. Wenn Sie jedoch ein htmlArgument zusammen mit einem bodyArgument übergeben, wird eine HTML-E-Mail gesendet (mit Fallback auf Textinhalte für E-Mail-Clients, die keine HTML- / MIME-Typen unterstützen).

Anwendungsbeispiel:

ex = send_email(
      host        = 'smtp.gmail.com'
   #, port        = 465 # OK
    , port        = 587  #OK
    , user        = "[email protected]"
    , pwd         = "xxx"
    , from_       = '[email protected]'
    , recipients  = ['[email protected]']
    , subject     = "Test from python"
    , body        = "Test from python - body"
    )
if ex: 
    print("Mail sending failed: %s" % ex)
else:
    print("OK - mail sent"

Übrigens. Wenn Sie Google Mail als Test- oder Produktions-SMTP-Server verwenden möchten, aktivieren Sie den temporären oder permanenten Zugriff auf weniger gesicherte Apps:

Robert Lujo
quelle