Tornado non-blocking SMTP client

2019-05-05 00:31发布

问题:

I'am looking for python async SMTP client to connect it with Torando IoLoop. I found only simple implmementation (http://tornadogists.org/907491/) but it's a blocking solution so it might bring performance issues.

Does anyone encountered non blocking SMTP client for Tornado? Some code snippet would be also very useful.

回答1:

I wrote solution based on threads and queue. One thread per tornado process. This thread is a worker, gets email from queue and then send it via SMTP. You send emails from tornado application by adding it to queue. Simple and easy.

Here is sample code on GitHub: link



回答2:

Just FYI - I just whipped up a ioloop based smtp client. While I can't say it's production tested, it will be in the near future.

https://gist.github.com/1358253



回答3:

https://github.com/equeny/tornadomail - here is my attemp to port django mail system and python smtplib to tornado ioloop. Will be happy to hear some feedback.



回答4:

I was looking for the solution to the same problem at work. Since there was no readily available solution, I ported Python smtplib to implementation based on tornado non-blocking IOStream. The syntax follows that of smtplib as close as possible.

# create SMTP client 
s = SMTPAsync()
yield s.connect('your.email.host',587)
yield s.starttls() 
yield s.login('username', 'password') 
yield s.sendmail('from_addr', 'to_addr', 'msg')

It currently only supports Python 3.3 and above. Here's the github repo



回答5:

I'm not using my own SMTP server but figured this would be useful to someone:

I've just had to add email sending to my app. Most of the sample python code for the web emailing services use a blocking design so I dont want to use it.

Mailchimp's Mandrill uses HTTP POST requests so it can work in an Async fashion fitting in with Tornado's design.

class EmailMeHandler(BaseHandler):
    @tornado.web.asynchronous
    @tornado.gen.engine
    def get(self):
        http_client = AsyncHTTPClient()
        mail_url = self.settings["mandrill_url"] + "/messages/send.json"
        mail_data = {
            "key": self.settings["mandrill_key"],
            "message": {
                "html": "html email from tornado sample app <b>bold</b>", 
                "text": "plain text email from tornado sample app", 
                "subject": "from tornado sample app", 
                "from_email": "hello@example.com", 
                "from_name": "Hello Team", 
                "to":[{"email": "sample@example.com"}]
            }
        }

        body = tornado.escape.json_encode(mail_data)
        response = yield tornado.gen.Task(http_client.fetch, mail_url, method='POST', body=body)
        logging.info(response)
        logging.info(response.body)

        if response.code == 200:
            self.redirect('/?notification=sent')
        else:
            self.redirect('/?notification=FAIL')