A simple SMTP server (in Python)

前端 未结 9 2584
小鲜肉
小鲜肉 2020-12-12 17:09

Could you please suggest a simple SMTP server with the very basic APIs (by very basic I mean, to read, write, delete email), that could be run on a linux box? I just need to

相关标签:
9条回答
  • 2020-12-12 18:04

    I also wanted to start a smtp server in Python and send emails with Python. I wanted to run all this in a Flask web application in a single process, which means the smtp server must be non-blocking. Here's the solution I eventually came to [gist]:

    app.py

    from flask import Flask, render_template
    from smtp_client import send_email
    from smtp_server import SMTPServer
    
    app = Flask(__name__)
    
    @app.route('/send_email')
    def email():
      server = SMTPServer()
      server.start()
      try:
        send_email()
      finally:
        server.stop()
      return 'OK'
    
    @app.route('/')
    def index():
      return 'Woohoo'
    
    if __name__ == '__main__':
      app.run(debug=True, host='0.0.0.0')
    

    smtp_server.py

    # smtp_server.py
    import smtpd
    import asyncore
    import threading
    
    class CustomSMTPServer(smtpd.SMTPServer):
      def process_message(self, peer, mailfrom, rcpttos, data):
        print('Receiving message from:', peer)
        print('Message addressed from:', mailfrom)
        print('Message addressed to:', rcpttos)
        print('Message length:', len(data))
        return
    
    class SMTPServer():
      def __init__(self):
        self.port = 1025
    
      def start(self):
        '''Start listening on self.port'''
        # create an instance of the SMTP server, derived from  asyncore.dispatcher
        self.smtp = CustomSMTPServer(('0.0.0.0', self.port), None)
        # start the asyncore loop, listening for SMTP connection, within a thread
        # timeout parameter is important, otherwise code will block 30 seconds
        # after the smtp channel has been closed
        kwargs = {'timeout':1, 'use_poll': True}
        self.thread = threading.Thread(target=asyncore.loop, kwargs=kwargs)
        self.thread.start()
    
      def stop(self):
        '''Stop listening to self.port'''
        # close the SMTPserver to ensure no channels connect to asyncore
        self.smtp.close()
        # now it is safe to wait for asyncore.loop() to exit
        self.thread.join()
    
      # check for emails in a non-blocking way
      def get(self):
        '''Return all emails received so far'''
        return self.smtp.emails
    
    if __name__ == '__main__':
      server = CustomSMTPServer(('0.0.0.0', 1025), None)
      asyncore.loop()
    

    smtp_client.py

    import smtplib
    import email.utils
    from email.mime.text import MIMEText
    
    def send_email():
      sender='author@example.com'
      recipient='6142546977@tmomail.net'
    
      msg = MIMEText('This is the body of the message.')
      msg['To'] = email.utils.formataddr(('Recipient', recipient))
      msg['From'] = email.utils.formataddr(('Author', 'author@example.com'))
      msg['Subject'] = 'Simple test message'
    
      client = smtplib.SMTP('127.0.0.1', 1025)
      client.set_debuglevel(True) # show communication with the server
      try:
        client.sendmail('author@example.com', [recipient], msg.as_string())
      finally:
        client.quit()
    

    Then start the server with python app.py and in another request simulate a request to /send_email with curl localhost:5000/send_email. Note that to actually send the email (or sms) you'll need to jump through other hoops detailed here: https://blog.codinghorror.com/so-youd-like-to-send-some-email-through-code/.

    0 讨论(0)
  • 2020-12-12 18:11

    There are really 2 things required to send an email:

    • An SMTP Server - This can either be the Python SMTP Server or you can use GMail or your ISP's server. Chances are you don't need to run your own.
    • An SMTP Library - Something that will send an email request to the SMTP server. Python ships with a library called smtplib that can do that for you. There is tons of information on how to use it here: http://docs.python.org/library/smtplib.html

    For reading, there are two options depending on what server you are reading the email from.

    • For a POP Email Server - You can use the poplib python library: http://docs.python.org/library/poplib.html
    • For an IMAP Email Server - You can use the imaplib python library: http://docs.python.org/library/imaplib.html
    0 讨论(0)
  • 2020-12-12 18:11

    To get Hasen's script working in Python 3 I had to tweak it slightly:

    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()
    
    0 讨论(0)
提交回复
热议问题