2008-12-08 58 views
32

¿Cómo puedo recibir y enviar correos electrónicos en python? Un 'servidor de correo' de algún tipo.Recibir y enviar correos electrónicos en python

Estoy buscando crear una aplicación que escuche si recibe un correo electrónico dirigido a [email protected] y envía un correo electrónico al remitente.

Ahora, ¿puedo hacer todo esto en python? ¿Sería mejor utilizar bibliotecas de terceros?

Respuesta

23

Aquí es un ejemplo muy sencillo:

import smtplib 

server = 'mail.server.com' 
user = '' 
password = '' 

recipients = ['[email protected]', '[email protected]'] 
sender = '[email protected]' 
message = 'Hello World' 

session = smtplib.SMTP(server) 
# if your SMTP server doesn't need authentications, 
# you don't need the following line: 
session.login(user, password) 
session.sendmail(sender, recipients, message) 

Para obtener más opciones, manejo de errores, etc, mira el smtplib module documentation.

+2

que cubre la parte de envío, si se puede añadir un fragmento rápido para escuchar si hay nuevos correos usando el módulo smptd esto sería una gran respuesta – Jay

+7

Nota esto está muy lejos de un servidor de correo electrónico real ya que la mayoría de lo real el trabajo (cola y retransmisión) se realiza por 'mail.server.com', no por el programa Python. – bortzmeyer

+0

tienes razón. está muy lejos de ser un servidor de correo real. –

2

Sí, puede hacer casi todo con las bibliotecas incorporadas. Haga una búsqueda aquí buscando las etiquetas [python] y [email] y verá cómo se hace.

4

poplib y smtplib serán tus amigos cuando desarrolles tu aplicación.

6

Python tiene un módulo SMTPD que le será útil para escribir un servidor. Probablemente también quiera que el módulo SMTP haga el reenvío. Ambos módulos están en la biblioteca estándar al menos desde la versión 2.3.

2

Dependiendo de la cantidad de correo que esté enviando, es posible que desee considerar utilizar un servidor de correo real como postifx o sendmail (* nix systems). Ambos programas tienen la capacidad de enviar un correo recibido a un programa basado en la direccion de correo electronico.

3

La parte que envía se ha cubierto, para la recepción de pop puede utilizar o imap

12

no creo que sería una buena idea para escribir un servidor de correo real en Python. Esto es ciertamente posible (ver las publicaciones de mcrute y Manuel Ceron para tener detalles) pero es mucho trabajo cuando piensas en todo lo que debe manejar un servidor de correo real (hacer cola, retransmitir, tratar con spam, etc.).

Debe explicar con más detalle lo que necesita. Si solo quiere reaccionar al correo electrónico entrante, le sugiero que configure el servidor de correo para llamar a un programa cuando reciba el correo electrónico. Este programa podría hacer lo que quiera (actualizar una base de datos, crear un archivo, hablar con otro programa de Python).

llamar a un programa arbitrario del servidor de correo, usted tiene varias opciones:

  1. Para Sendmail y Postfix, un ~/.forward contienen "|/path/to/program"
  2. Si utiliza procmail, una acción de la receta de |path/to/program
  3. Y ciertamente muchos otros
+0

Odio cuando las personas votan sin agregar un comentario. ¿Cuál fue el problema con mi respuesta? – bortzmeyer

+0

No sé cuál sería el problema. Básicamente es mi respuesta con más detalles. Creo que esta es una buena solución. – epochwolf

+0

En realidad, el servidor smtpd de python es bastante bueno para las aplicaciones internas que lo he usado. SMTP realmente no es tan difícil de resolver, la parte difícil es la multiplexación de las conexiones de red. Sin embargo, no estoy seguro de que lo use para manejar la carga de producción "real". – mcrute

12

Encontramos un ejemplo útil para leer correos electrónicos mediante la conexión usando IMAP:

Python — imaplib IMAP example with Gmail

import imaplib 
mail = imaplib.IMAP4_SSL('imap.gmail.com') 
mail.login('[email protected]', 'mypassword') 
mail.list() 
# Out: list of "folders" aka labels in gmail. 
mail.select("inbox") # connect to inbox. 
result, data = mail.search(None, "ALL") 

ids = data[0] # data is a list. 
id_list = ids.split() # ids is a space separated string 
latest_email_id = id_list[-1] # get the latest 

# fetch the email body (RFC822) for the given ID 
result, data = mail.fetch(latest_email_id, "(RFC822)") 

raw_email = data[0][1] # here's the body, which is raw text of the whole email 
# including headers and alternate payloads 
+0

Gracias por el enlace, este es un gran recurso. IMAP4 es más avanzado que POP3, pero ofrece más capacidades, como ser capaz de buscar a través de encabezados. – Joansy

1

La mejor manera de hacer esto sería la creación de un servicio de Windows en Python que recibe los mensajes de correo electrónico utilizando imaplib2

A continuación se muestra un ejemplo de script Python para hacer el same.You puede instale este script para que se ejecute como un servicio de Windows ejecutando el siguiente comando en la línea de comando "python THENAMEOFYOURSCRIPTFILE.py install".

import win32service 
import win32event 
import servicemanager 
import socket 
import imaplib2, time 
from threading import * 
import smtplib 
from email.MIMEMultipart import MIMEMultipart 
from email.MIMEText import MIMEText 
import datetime 
import email 

class Idler(object): 
    def __init__(self, conn): 
     self.thread = Thread(target=self.idle) 
     self.M = conn 
     self.event = Event() 

    def start(self): 
     self.thread.start() 

    def stop(self): 
     self.event.set() 

    def join(self): 
     self.thread.join() 

    def idle(self): 
     while True: 
      if self.event.isSet(): 
       return 
      self.needsync = False 
      def callback(args): 
       if not self.event.isSet(): 
        self.needsync = True 
        self.event.set() 
      self.M.idle(callback=callback) 
      self.event.wait() 
      if self.needsync: 
       self.event.clear() 
       self.dosync() 


    def dosync(self): 
     #DO SOMETHING HERE WHEN YOU RECEIVE YOUR EMAIL 

class AppServerSvc (win32serviceutil.ServiceFramework): 
    _svc_name_ = "receiveemail" 
    _svc_display_name_ = "receiveemail" 


    def __init__(self,args): 
     win32serviceutil.ServiceFramework.__init__(self,args) 
     self.hWaitStop = win32event.CreateEvent(None,0,0,None) 
     socket.setdefaulttimeout(60) 

    def SvcStop(self): 
     self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) 
     win32event.SetEvent(self.hWaitStop) 

    def SvcDoRun(self): 
     servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, 
           servicemanager.PYS_SERVICE_STARTED, 
           (self._svc_name_,'')) 
     self.main() 

    def main(self): 
     M = imaplib2.IMAP4_SSL("imap.gmail.com", 993) 
     M.login("YourID", "password") 
     M.select("INBOX") 
     idler = Idler(M) 
     idler.start() 
     while True: 
      time.sleep(1*60) 
     idler.stop() 
     idler.join() 
     M.close() 
     M.logout() 

if __name__ == '__main__': 
    win32serviceutil.HandleCommandLine(AppServerSvc) 
+0

Esto se ve innecesariamente complejo a mi vista. ¿Qué gana al hacer de este un servicio de Windows, en lugar de simplemente mantenerlo como un hilo o proceso (independiente de la plataforma)? – Ponkadoodle

+0

@Wallacoloo. Escribí esto con el sistema operativo Windows en mente. Algo que se ejecuta para siempre se ejecuta mejor como un servicio de Windows. Los beneficios de un servicio definitivamente valen la pena la complejidad añadida. Mi humilde opinión. – ambassallo

Cuestiones relacionadas