Un servidor SMTP simple (en Python)

¿Podría, por favor, sugerir un simple servidor SMTP con las API muy básicas (me refiero a leer, escribir, eliminar correo electrónico) que podría ejecutarse en una caja de Linux? Solo necesito convertir el quid del correo electrónico al formato XML y enviarlo por FTP a otra máquina.

Echa un vistazo a este servidor receptor SMTP :

from datetime import datetime import asyncore from smtpd import SMTPServer class EmlServer(SMTPServer): no = 0 def process_message(self, peer, mailfrom, rcpttos, data): filename = '%s-%d.eml' % (datetime.now().strftime('%Y%m%d%H%M%S'), self.no) f = open(filename, 'w') f.write(data) f.close print '%s saved.' % filename self.no += 1 def run(): foo = EmlServer(('localhost', 25), None) try: asyncore.loop() except KeyboardInterrupt: pass if __name__ == '__main__': run() 

Utiliza smtpd.SMTPServer para volcar correos electrónicos a archivos.

Realmente hay 2 cosas necesarias para enviar un correo electrónico:

  • Un servidor SMTP: puede ser el servidor SMTP de Python o puede usar GMail o el servidor de su ISP. Es probable que no necesites correr el tuyo.
  • Una biblioteca SMTP: algo que enviará una solicitud por correo electrónico al servidor SMTP. Python se envía con una biblioteca llamada smtplib que puede hacer eso por ti. Hay toneladas de información sobre cómo usarlo aquí: http://docs.python.org/library/smtplib.html

Para la lectura, hay dos opciones según el servidor desde el que está leyendo el correo electrónico.

Los dos servidores Python Smtp que he usado con éxito son:

  1. Twisted’s Mail – Una biblioteca de correo muy flexible para SMTP, IMAP, …
  2. python-slimta – Un MTA completo (servidor de retransmisión / reenvío smtp)

El ejemplo de Twisted se muestra abajo.

 # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details. # You can run this module directly with: # twistd -ny emailserver.tac """ A toy email server. """ from __future__ import print_function from zope.interface import implementer from twisted.internet import defer from twisted.mail import smtp from twisted.mail.imap4 import LOGINCredentials, PLAINCredentials from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse from twisted.cred.portal import IRealm from twisted.cred.portal import Portal @implementer(smtp.IMessageDelivery) class ConsoleMessageDelivery: def receivedHeader(self, helo, origin, recipients): return "Received: ConsoleMessageDelivery" def validateFrom(self, helo, origin): # All addresses are accepted return origin def validateTo(self, user): # Only messages directed to the "console" user are accepted. if user.dest.local == "console": return lambda: ConsoleMessage() raise smtp.SMTPBadRcpt(user) @implementer(smtp.IMessage) class ConsoleMessage: def __init__(self): self.lines = [] def lineReceived(self, line): self.lines.append(line) def eomReceived(self): print("New message received:") print("\n".join(self.lines)) self.lines = None return defer.succeed(None) def connectionLost(self): # There was an error, throw away the stored lines self.lines = None class ConsoleSMTPFactory(smtp.SMTPFactory): protocol = smtp.ESMTP def __init__(self, *a, **kw): smtp.SMTPFactory.__init__(self, *a, **kw) self.delivery = ConsoleMessageDelivery() def buildProtocol(self, addr): p = smtp.SMTPFactory.buildProtocol(self, addr) p.delivery = self.delivery p.challengers = {"LOGIN": LOGINCredentials, "PLAIN": PLAINCredentials} return p @implementer(IRealm) class SimpleRealm: def requestAvatar(self, avatarId, mind, *interfaces): if smtp.IMessageDelivery in interfaces: return smtp.IMessageDelivery, ConsoleMessageDelivery(), lambda: None raise NotImplementedError() def main(): from twisted.application import internet from twisted.application import service portal = Portal(SimpleRealm()) checker = InMemoryUsernamePasswordDatabaseDontUse() checker.addUser("guest", "password") portal.registerChecker(checker) a = service.Application("Console SMTP Server") internet.TCPServer(2500, ConsoleSMTPFactory(portal)).setServiceParent(a) return a application = main() 

Estos son buenos ejemplos para empezar.

smtpd – Servidores SMTP de muestra

http://pymotw.com/2/smtpd/index.html

smtplib – cliente de protocolo simple de transferencia de correo

http://pymotw.com/2/smtplib/index.html

Un enfoque más moderno es usar la biblioteca aiosmtpd (la documentación está disponible aquí ).

Puede encontrar un buen ejemplo aquí: https://aiosmtpd.readthedocs.io/en/latest/aiosmtpd/docs/controller.html .

Hay un servidor SMTP de Python .

Este módulo ofrece varias clases para implementar servidores SMTP. Una es una implementación genérica de no hacer nada, que puede ser anulada, mientras que las otras dos ofrecen estrategias específicas de envío de correo.

Para que el script de Hasen funcionara en Python 3 tuve que modificarlo ligeramente:

 from datetime import datetime import asyncore from smtpd import SMTPServer class EmlServer(SMTPServer): no = 0 def process_message(self, peer, mailfrom, rcpttos, data, **kwargs): filename = '%s-%d.eml' % (datetime.now().strftime('%Y%m%d%H%M%S'), self.no) print(filename) f = open(filename, 'wb') f.write(data) f.close print('%s saved.' % filename) self.no += 1 def run(): EmlServer(('localhost', 25), None) try: asyncore.loop() except KeyboardInterrupt: pass if __name__ == '__main__': run() 

Si quieres probar rápidamente el send_mail de Django con la respuesta de hasen arriba:

 # Skip lines 3 and 4 if not using virtualenv. # At command prompt mkdir django1 cd django1 virtualenv venv source venv/bin/activate pip install django==1.11 django-admin startproject django1 . # run the Django shell python manage.py shell # paste into shell following: from django.core.mail import send_mail send_mail( 'Subject here', 'Here is the message.', 'from@example.com', ['to@example.com'], fail_silently=False, ) # This should write an email like the following: Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Subject here From: from@example.com To: to@example.com Date: Wed, 02 May 2018 02:12:09 -0000 Message-ID: <20180502021209.32641.51865@i1022> Here is the message. 

No es necesario tener valores válidos en la función send_mail. Los valores anteriores funcionarán bien con el ejemplo de hasen.