python - leer - smtplib cc
¿Cómo enviar un correo electrónico con Python? (10)
Este código funciona y me envía un correo electrónico muy bien:
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()
Sin embargo, si intento envolverlo en una función como esta:
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()
y llámalo obtengo los siguientes errores:
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
¿Alguien puede ayudarme a entender por qué?
Aquí hay un ejemplo en Python 3.x
, mucho más simple que 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.'')
llamar a esta función:
send_mail(to_email=[''[email protected]'', ''[email protected]''],
subject=''hello'', message=''Your analysis has done!'')
debajo puede ser solo para el usuario chino:
Si usa 126/163, 网易 邮箱, debe configurar "客户 端 授权,", como a continuación:
ref: https://.com/a/41470149/2803344 https://docs.python.org/3/library/email.examples.html#email-examples
Bueno, quieres tener una respuesta actualizada y moderna.
Aquí está mi respuesta:
Cuando necesito enviar un correo electrónico a Python, uso la API de correo comprimido, que me da muchos dolores de cabeza al enviar mensajes resueltos. Tienen una maravillosa aplicación / api que te permite enviar 10.000 correos electrónicos por mes de forma gratuita.
Enviar un correo electrónico sería así:
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 <mailgun@YOUR_DOMAIN_NAME>",
"to": ["[email protected]", "YOU@YOUR_DOMAIN_NAME"],
"subject": "Hello",
"text": "Testing some Mailgun awesomness!"})
También puede rastrear eventos y mucho más, consulte la guía de inicio rápido .
¡Espero que encuentres esto útil!
En lo que respecta a su código, no parece haber nada fundamentalmente erróneo excepto que no está claro cómo llama realmente a esa función. Todo lo que puedo pensar es que cuando su servidor no responda, obtendrá este error SMTPServerDisconnected. Si busca la función getreply () en smtplib (extracto a continuación), obtendrá una idea.
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.
"""
verifique un ejemplo en https://github.com/rreddy80/sendEmails/blob/master/sendEmailAttachments.py que también utiliza una llamada a función para enviar un correo electrónico, si eso es lo que intenta hacer (enfoque DRY).
Hay un problema de sangría. El siguiente código funcionará:
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()
Me gustaría ayudarlo enviando correos electrónicos aconsejándome el paquete yagmail (soy el mantenedor, lo siento por la publicidad, pero creo que realmente puede ayudar).
El código completo para usted sería:
import yagmail
yag = yagmail.SMTP(FROM, ''pass'')
yag.send(TO, SUBJECT, TEXT)
Tenga en cuenta que proporciono los valores predeterminados para todos los argumentos, por ejemplo, si desea enviarse a usted mismo, puede omitir TO
, si no desea un tema, puede omitirlo también.
Además, el objetivo también es hacer que sea realmente fácil adjuntar código html o imágenes (y otros archivos).
Donde colocas contenidos puedes hacer algo como:
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'']
Guau, ¡qué fácil es enviar archivos adjuntos! Esto tomaría como 20 líneas sin yagmail;)
Además, si lo configura una vez, nunca más tendrá que ingresar la contraseña (y guardarla de manera segura). En tu caso, puedes hacer algo como:
import yagmail
yagmail.SMTP().send(contents = contents)
¡que es mucho más conciso!
Te invito a echar un vistazo al yagmail o instalarlo directamente con pip install yagmail
.
Mientras sangra su código en la función (que está bien), también sangró las líneas de la cadena de mensaje sin formato. Pero el espacio blanco inicial implica el plegamiento (concatenación) de las líneas de encabezado, como se describe en las secciones 2.2.3 y 3.2.3 de RFC 2822 - Formato de mensaje de Internet :
Cada campo de encabezado es lógicamente una sola línea de caracteres que comprende el nombre del campo, los dos puntos y el cuerpo del campo. Sin embargo, para su comodidad, y para tratar con las limitaciones de 998/78 caracteres por línea, la parte del cuerpo del campo de un encabezado se puede dividir en una representación de múltiples líneas; esto se llama "plegado".
En la forma de función de su llamada a sendmail
, todas las líneas comienzan con espacios en blanco y, por lo tanto, están "desplegadas" (concatenadas) y usted está tratando de enviarlas.
From: [email protected] To: [email protected] Subject: Hello! This message was sent with Python''s smtplib.
Aparte de lo que nuestra mente sugiere, smtplib
ya no comprenderá los encabezados To:
y Subject:
ya que estos nombres solo se reconocen al comienzo de una línea. En cambio, smtplib
asumirá una dirección de correo electrónico del remitente muy larga:
[email protected] To: [email protected] Subject: Hello! This message was sent with Python''s smtplib.
Esto no funcionará, y también su Excepción.
La solución es simple: solo conserva la cadena del message
como estaba antes. Esto se puede hacer mediante una función (como sugirió Zeeshan) o directamente en el código fuente:
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()
Ahora el despliegue no ocurre y envías
From: [email protected]
To: [email protected]
Subject: Hello!
This message was sent with Python''s smtplib.
que es lo que funciona y lo que hizo tu antiguo código.
Tenga en cuenta que también estaba preservando la línea vacía entre los encabezados y el cuerpo para acomodar la sección 3.5 del RFC (que se requiere) y poner el include fuera de la función de acuerdo con la guía de estilo Python PEP-0008 (que es opcional).
Pensé que pondría mis dos cosas aquí, ya que acabo de descubrir cómo funciona esto.
Parece que no tiene el puerto especificado en la configuración de conexión de SERVER, esto me afectó un poco cuando intenté conectarme a mi servidor SMTP que no usa el puerto predeterminado: 25.
De acuerdo con los documentos smtplib.SMTP, su solicitud / respuesta de ehlo o helo debería resolverse automáticamente, por lo que no debería tener que preocuparse por esto (pero podría ser algo para confirmar si todo lo demás falla).
Otra cosa que debe preguntarse es si ha permitido las conexiones SMTP en su servidor SMTP. Para algunos sitios como GMAIL y ZOHO, debes ingresar y activar las conexiones IMAP dentro de la cuenta de correo electrónico. ¿Su servidor de correo puede no permitir conexiones SMTP que no provienen de ''localhost'' quizás? Algo para mirar.
Lo último es que es posible que desee probar e iniciar la conexión en TLS. La mayoría de los servidores ahora requieren este tipo de autenticación.
Verás que he atascado dos campos TO en mi correo electrónico. Los elementos del diccionario msg [''TO''] y msg [''FROM''] permiten que la información correcta aparezca en los encabezados del correo electrónico, que se ve en el extremo receptor del correo electrónico en los campos Para / De ( incluso podría agregar un campo Responder a aquí. Los campos TO y FROM son lo que necesita el servidor. Sé que he oído que algunos servidores de correo electrónico rechazan los correos electrónicos si no tienen los encabezados adecuados.
Este es el código que he usado, en una función, que funciona para enviar por correo electrónico el contenido de un archivo * .txt usando mi computadora local y un servidor SMTP remoto (ZOHO como se muestra):
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()
Probablemente esté poniendo pestañas en su mensaje. Imprima el mensaje antes de pasarlo a sendMail.
Prueba esto:
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()
Funciona para smtp.gmail.com
Recomiendo que utilices los paquetes estándar de email
y smtplib
para enviar correos electrónicos. Mire el siguiente ejemplo (reproducido de la documentación de Python ). Tenga en cuenta que si sigue este enfoque, la tarea "simple" es de hecho simple, y las tareas más complejas (como la vinculación de objetos binarios o el envío de mensajes multiparte simple / HTML) se llevan a cabo muy rápidamente.
# 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()
Para enviar correos electrónicos a múltiples destinos, también puede seguir el ejemplo en la documentación de Python :
# 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()
Como puede ver, el encabezado To
en el objeto MIMEText
debe ser una cadena que consta de direcciones de correo electrónico separadas por comas. Por otro lado, el segundo argumento para la función sendmail
debe ser una lista de cadenas (cada cadena es una dirección de correo electrónico).
Por lo tanto, si tiene tres direcciones de correo electrónico: [email protected]
, [email protected]
y [email protected]
, puede hacer lo siguiente (se omiten las secciones obvias):
to = ["[email protected]", "[email protected]", "[email protected]"]
msg[''To''] = ",".join(to)
s.sendmail(me, to, msg.as_string())
la parte "","".join(to)
hace una sola cadena fuera de la lista, separada por comas.
A partir de sus preguntas, sé que no ha asistido al tutorial de Python ; es IMPRESCINDIBLE si desea llegar a algún lado en Python; la documentación es en su mayoría excelente para la biblioteca estándar.