Invio di posta da Python tramite SMTP


118

Sto usando il seguente metodo per inviare posta da Python usando SMTP. È il metodo giusto da usare o ci sono trucchi che mi mancano?

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 <john@doe.net>"
to_addr = "foo@bar.com"

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()

2
Assicurati di ottenere la data / ora corretta. Ho trovato la seguente funzione abbastanza utile, che ti dà un valore perfettamente formattato per Date-Header: docs.python.org/py3k/library/…
BastiBen

ecco un esempio di codice che consente di inviare e-mail con testo Unicode nell'oggetto e / o nel corpo
jfs

ecco un esempio di codice che dimostra come inviare immagini in linea (oltre a email con parti HTML e testo normale) . Mostra anche come configurare i parametri ssl sulle vecchie versioni di Python.
jfs

2
Nota che sono disponibili librerie wrapper che rendono molto meno codice per inviare e-mail (come yagmail )
PascalVKooten

Risposte:


111

Lo script che uso è abbastanza simile; Lo posto qui come esempio di come utilizzare i moduli email. * Per generare messaggi MIME; quindi questo script può essere facilmente modificato per allegare immagini, ecc.

Mi affido al mio ISP per aggiungere l'intestazione della data e dell'ora.

Il mio ISP mi richiede di utilizzare una connessione smtp sicura per inviare la posta, mi affido al modulo smtplib (scaricabile da http://www1.cs.columbia.edu/~db2501/ssmtplib.py )

Come nel tuo script, il nome utente e la password, (dati valori fittizi di seguito), utilizzati per l'autenticazione sul server SMTP, sono in testo normale nell'origine. Questa è una debolezza della sicurezza; ma la migliore alternativa dipende da quanta attenzione hai bisogno (vuoi?) per proteggerli.

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

#! /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

1
@ Vincent: posta non riuscita; L'oggetto "module" non ha attributi "SSLFakeSocket" - utilizzando Gmail :(
RadiantHex

Sembra una versione o un problema di importazione, per aiutarti a rintracciarlo: quale versione Python stai utilizzando? - Hai bisogno di connetterti al tuo server SMTP su SSL (e se sì stai importando ssmtplib, come sopra)? Puoi importare smtplib direttamente da python interactive, in tal caso, esiste una classe smtplib.SSLFakeSocket definita? Spero di poter aiutare
Vincent Marchetti

2
Usa smtplib.SMTP_SSL (standard nelle ultime versioni di Python) per creare la connessione invece di ssmtplib.STMP_SSL (modulo di terze parti suggerito sopra). Notare che il modulo standard inizia con una singola 's'. Ha funzionato per me.
Julio Gorgé

2
sostituire from ssmtplib import SMTP_SSL as SMTPcon from smtplib import SMTP_SSL as SMTP, e questo esempio funzionerebbe dalla libreria Python standard.
Adam Matan

9
Aggiungi msg['To'] = ','.join(destination), altrimenti la destinazione non viene visualizzata in Gmail
Taha Jahangir

88

Il metodo che uso comunemente ... non molto diverso ma un po '

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

msg = MIMEMultipart()
msg['From'] = 'me@gmail.com'
msg['To'] = 'you@gmail.com'
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('me@gmail.com', 'mypassword')

mailserver.sendmail('me@gmail.com','you@gmail.com',msg.as_string())

mailserver.quit()

Questo è tutto


Se utilizzi la verifica in due passaggi, devi prima creare una password specifica per l'app e sostituirla con la tua password normale. Vedi Accesso utilizzando password per le app
Suzana

2
Sono d'accordo, questa è la risposta migliore e dovrebbe essere accettata. Quello che è effettivamente accettato è inferiore.
HelloWorld

6
Per python3, usa:from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText
art

21

Inoltre, se si desidera eseguire l'autenticazione smtp con TLS anziché SSL, è sufficiente modificare la porta (utilizzare 587) e eseguire smtp.starttls (). Questo ha funzionato per me:

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

6

Il problema principale che vedo è che non stai gestendo alcun errore: .login () e .sendmail () hanno entrambi eccezioni documentate che possono generare, e sembra che .connect () debba avere un modo per indicare che lo è stato impossibile connettersi, probabilmente un'eccezione generata dal codice socket sottostante.


6

Assicurati di non avere firewall che bloccano SMTP. La prima volta che ho provato a inviare un'e-mail, è stata bloccata sia da Windows Firewall che da McAfee - ci è voluta un'eternità per trovarli entrambi.


6

Che dire di questo?

import smtplib

SERVER = "localhost"

FROM = "sender@example.com"
TO = ["user@example.com"] # 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()

4

il seguente codice funziona bene per me:

import smtplib

to = 'mkyong2002@yahoo.com'
gmail_user = 'mkyong2002@gmail.com'
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()

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


1
Flask ha un framework per la posta elettronica: da flask.ext.mail importa Mail. Sto risolvendo i problemi e ho pensato di tornare al codice Python per vedere se riuscivo a far funzionare qualcosa. Mi è piaciuta questa risposta perché era ossa nude. Oh sì, e ha funzionato!

Attenzione: la versione precedente della risposta includeva la riga: smtpserver.close()Deve essere:, smtpserver.quit()perché close()non terminerà correttamente la connessione TLS! close()sarà chiamato durante quit().
aronadaal

Ciao, ho problemi a eseguire i comandi precedenti. quando uso smtpserver.starttls (), ottengo un errore SMTP "SMTPServerDisconnected: Collegamento inaspettatamente chiuso: [Errno 10054]" .. riportato in stackoverflow.com/questions/46094175/...
fazkan


3

Il codice di esempio che ho fatto per inviare posta tramite SMTP.

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()

2

Vedi tutte quelle lunghe risposte? Per favore, permettimi di promuovermi da solo facendo tutto in un paio di righe.

Importa e connetti:

import yagmail
yag = yagmail.SMTP('john@doe.net', host = 'YOUR.MAIL.SERVER', port = 26)

Quindi è solo una frase:

yag.send('foo@bar.com', 'hello', 'Hello\nThis is a mail from your server\n\nBye\n')

Si chiuderà effettivamente quando esce dall'ambito (o può essere chiuso manualmente). Inoltre, ti permetterà di registrare il tuo nome utente nel tuo portachiavi in ​​modo tale da non dover scrivere la tua password nel tuo script (mi dava davvero fastidio prima di scrivere yagmail!)

Per il pacchetto / installazione, suggerimenti e trucchi, guarda git o pip , disponibili sia per Python 2 che per 3.


@PascalvKoolen Ho installato yagmail e ho provato a connettermi fornendo il mio ID e-mail e la password. ma mi ha dato un errore di autenticazione
fazkan

0

puoi fare così

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 = 'me@servername.com'
to = 'mygfriend@servername.com'
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)

0

Ecco un esempio funzionante per 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 = 'your_email_address@gmail.com'
password = getpass('Enter Gmail password: ')

sender = 'your_email_address@gmail.com'
destination = 'recipient_email_address@gmail.com'
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)))

0

Sulla base di questo esempio ho creato la seguente funzione:

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

se passi solo body, verrà inviata posta di testo normale, ma se passi un htmlargomento insieme bodyall'argomento, verrà inviata un'e-mail html (con fallback al contenuto di testo per i client di posta che non supportano i tipi html / mime).

Utilizzo di esempio:

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

Btw. Se desideri utilizzare Gmail come server SMTP di test o di produzione, abilita l'accesso temporaneo o permanente alle app meno sicure:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.