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 trato de 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 lo llamo me sale 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é?
Respuestas:
Le recomiendo que use los paquetes estándar
email
ysmtplib
juntos 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 realmente simple, y las tareas más complejas (como adjuntar objetos binarios o enviar mensajes multiparte sin formato / HTML) se realizan muy rápidamente.Para enviar correos electrónicos a múltiples destinos, también puede seguir el ejemplo en la documentación de Python :
Como puede ver, el encabezado
To
delMIMEText
objeto debe ser una cadena que consta de direcciones de correo electrónico separadas por comas. Por otro lado, el segundo argumento de lasendmail
función 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]
, se puede hacer de la siguiente manera (secciones obvias omitidas):la
",".join(to)
parte forma una sola cadena fuera de la lista, separada por comas.De sus preguntas, deduzco que no ha seguido el tutorial de Python , es imprescindible si desea llegar a cualquier lugar de Python, la documentación es en su mayoría excelente para la biblioteca estándar.
fuente
", ".join(["[email protected]", "[email protected]"])
with
:with open(textfile, 'rb') as fp:
. El cierre explícito se puede descartar, ya que elwith
bloque cerrará el archivo incluso si se produce un error dentro de él.Bueno, desea tener una respuesta actualizada y moderna.
Aquí está mi respuesta:
Cuando necesito enviar un correo electrónico a Python, utilizo la API de mailgun , que me causa muchos dolores de cabeza al enviar correos ordenados. Tienen una aplicación / api maravillosa que te permite enviar 10,000 correos electrónicos por mes de forma gratuita.
Enviar un correo electrónico sería así:
También puede realizar un seguimiento de eventos y mucho más, consulte la guía de inicio rápido .
¡Espero que encuentres esto útil!
fuente
Me gustaría ayudarlo con el envío de correos electrónicos informando sobre el paquete de yagmail (soy el encargado de mantener, lo siento por la publicidad, ¡pero creo que realmente puede ayudar!).
El código completo para ti sería:
Tenga en cuenta que proporciono valores predeterminados para todos los argumentos, por ejemplo, si desea enviarse a sí mismo, puede omitir
TO
, si no desea un asunto, también puede omitirlo.Además, el objetivo también es hacer que sea realmente fácil adjuntar código html o imágenes (y otros archivos).
Donde pones contenidos puedes hacer algo como:
¡Qué fácil es enviar archivos adjuntos! Esto tomaría como 20 líneas sin yagmail;)
Además, si lo configura una vez, nunca tendrá que volver a ingresar la contraseña (y guardarla de forma segura). En tu caso puedes hacer algo como:
lo cual es mucho más conciso!
Te invito a echar un vistazo a Github o instalarlo directamente con
pip install yagmail
.fuente
yagmail
otro que no sea gmail? Estoy tratando de usar para mi propio servidor SMTP.Attachment
clase; Sigue siendo lo mismo. Si pueden cambiar su código, pueden hacer lo que quieran de todos modos (con / sin root, ese es el mismo envío de correo electrónico wrt). Esto me parece el típico "es conveniente / mágico, por lo que debe ser menos seguro". Tengo curiosidad por saber qué amenaza real ves.Hay un problema de sangría. El siguiente código funcionará:
fuente
SERVER
variable que se pasa a la función son las credenciales de usuario.email
biblioteca de Python hace esto razonablemente bien (particularmente desde 3.6) aunque aún requiere cierta comprensión de lo que está haciendo.Aquí hay un ejemplo en Python
3.x
, mucho más simple que2.x
:llama a esta función:
a continuación puede solo para usuarios chinos:
Si usa 126/163, 网易 邮箱, debe configurar "客户 端 授权 密码", como se muestra a continuación:
ref: https://stackoverflow.com/a/41470149/2803344 https://docs.python.org/3/library/email.examples.html#email-examples
fuente
Al sangrar su código en la función (que está bien), también sangró las líneas de la cadena de mensaje sin procesar. Pero el espacio en blanco inicial implica el plegado (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 :
En la forma de la función de su
sendmail
llamada, todas las líneas comienzan con espacios en blanco y, por lo tanto, están "desplegadas" (concatenadas) y está intentando enviarAparte de lo que sugiere nuestra mente,
smtplib
ya no entenderá los encabezadosTo:
ySubject:
, porque estos nombres solo se reconocen al comienzo de una línea. Ensmtplib
su lugar , asumirá una dirección de correo electrónico del remitente muy larga:Esto no funcionará y entonces viene tu Excepción.
La solución es simple: simplemente conserva la
message
cadena como estaba antes. Esto puede hacerse mediante una función (como sugirió Zeeshan) o de inmediato en el código fuente:Ahora el despliegue no ocurre y envías
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 puse el incluir fuera de la función de acuerdo con la guía de estilo Python PEP-0008 (que es opcional).
fuente
Probablemente esté poniendo pestañas en su mensaje. Imprima el mensaje antes de pasarlo a sendMail.
fuente
Asegúrese de haber otorgado permiso para que el remitente y el receptor envíen correos electrónicos y reciban correos electrónicos de fuentes desconocidas (fuentes externas) en la cuenta de correo electrónico.
fuente
msg
no es un mensaje SMTP válido, y simplemente parecerá desaparecer en el éter si su servidor de correo lo acepta.Pensé en poner mis dos partes 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 su SERVIDOR, esto me afectó un poco cuando intentaba conectarme a mi servidor SMTP que no usa el puerto predeterminado: 25.
De acuerdo con los documentos smtplib.SMTP, su solicitud / respuesta ehlo o helo debe ser atendida 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 conexiones SMTP en su servidor SMTP. Para algunos sitios como GMAIL y ZOHO, debe ingresar y activar las conexiones IMAP dentro de la cuenta de correo electrónico. ¿Es posible que su servidor de correo no permita conexiones SMTP que no provienen de 'localhost'? Algo a tener en cuenta.
Lo último es que puede intentar 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 se muestre la información correcta en los encabezados del correo electrónico, que se ve en el extremo receptor del correo electrónico en los campos Para / De (usted incluso podría agregar un campo Responder a aquí. Los campos TO y FROM son lo que requiere el servidor. Sé que he oído hablar de algunos servidores de correo electrónico que rechazan los correos electrónicos si no tienen los encabezados de correo electrónico adecuados.
Este es el código que he usado, en una función, que me 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):
fuente
Vale la pena señalar que el módulo SMTP es compatible con el administrador de contexto, por lo que no es necesario llamar manualmente a quit (), esto garantizará que siempre se llame incluso si hay una excepción.
fuente
En lo que respecta a su código, no parece haber nada fundamentalmente incorrecto, excepto que no está claro cómo llama realmente a esa función. Todo lo que puedo pensar es que cuando su servidor no responde, obtendrá este error SMTPServerDisconnected. Si busca la función getreply () en smtplib (extracto a continuación), obtendrá una idea.
consulte un ejemplo en https://github.com/rreddy80/sendEmails/blob/master/sendEmailAttachments.py que también utiliza una llamada de función para enviar un correo electrónico, si eso es lo que está tratando de hacer (enfoque DRY).
fuente