From 32b6364bcd1a17bfb6199af06ae613adf69e5058 Mon Sep 17 00:00:00 2001 From: Berend Iwema Date: Wed, 14 Aug 2013 12:59:01 +0200 Subject: [PATCH] #327 - Support STARTTLS / SSL option in email sender --- docs/topics/email.rst | 28 ++++++++++++++++++++++++++-- scrapy/mail.py | 18 +++++++++++++----- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/docs/topics/email.rst b/docs/topics/email.rst index 05628c479..a487299f1 100644 --- a/docs/topics/email.rst +++ b/docs/topics/email.rst @@ -39,11 +39,11 @@ MailSender class reference ========================== MailSender is the preferred class to use for sending emails from Scrapy, as it -uses `Twisted non-blocking IO`_, like the rest of the framework. +uses `Twisted non-blocking IO`_, like the rest of the framework. .. class:: MailSender(smtphost=None, mailfrom=None, smtpuser=None, smtppass=None, smtpport=None) - :param smtphost: the SMTP host to use for sending the emails. If omitted, the + :param smtphost: the SMTP host to use for sending the emails. If omitted, the :setting:`MAIL_HOST` setting will be used. :type smtphost: str @@ -62,6 +62,12 @@ uses `Twisted non-blocking IO`_, like the rest of the framework. :param smtpport: the SMTP port to connect to :type smtpport: int + :param smtptls: enforce using SMTP STARTTLS + :type smtpport: boolean + + :param smtpssl: enforce using a secure SSL connection + :type smtpport: boolean + .. classmethod:: from_settings(settings) Instantiate using a Scrapy settings object, which will respect @@ -148,3 +154,21 @@ MAIL_PASS Default: ``None`` Password to use for SMTP authentication, along with :setting:`MAIL_USER`. + +.. setting:: MAIL_TLS + +MAIL_TLS +--------- + +Default: ``False`` + +Enforce using STARTTLS. STARTTLS is a way to take an existing insecure connection, and upgrade it to a secure connection using SSL/TLS. + +.. setting:: MAIL_SSL + +MAIL_SSL +--------- + +Default: ``False`` + +Enforce connecting using an SSL encrypted connection diff --git a/scrapy/mail.py b/scrapy/mail.py index 8af6efdc4..bedf06895 100644 --- a/scrapy/mail.py +++ b/scrapy/mail.py @@ -11,7 +11,7 @@ from email.MIMEText import MIMEText from email.Utils import COMMASPACE, formatdate from email import Encoders -from twisted.internet import defer, reactor +from twisted.internet import defer, reactor, ssl from twisted.mail.smtp import ESMTPSenderFactory from scrapy import log @@ -19,18 +19,21 @@ from scrapy import log class MailSender(object): def __init__(self, smtphost='localhost', mailfrom='scrapy@localhost', - smtpuser=None, smtppass=None, smtpport=25, debug=False): + smtpuser=None, smtppass=None, smtpport=25, smtptls=False, smtpssl=False, debug=False): self.smtphost = smtphost self.smtpport = smtpport self.smtpuser = smtpuser self.smtppass = smtppass + self.smtptls = smtptls + self.smtpssl = smtpssl self.mailfrom = mailfrom self.debug = debug @classmethod def from_settings(cls, settings): return cls(settings['MAIL_HOST'], settings['MAIL_FROM'], settings['MAIL_USER'], - settings['MAIL_PASS'], settings.getint('MAIL_PORT')) + settings['MAIL_PASS'], settings.getint('MAIL_PORT'), + settings.getbool('MAIL_TLS'), settings.getbool('MAIL_SSL')) def send(self, to, subject, body, cc=None, attachs=(), _callback=None): if attachs: @@ -91,7 +94,12 @@ class MailSender(object): d = defer.Deferred() factory = ESMTPSenderFactory(self.smtpuser, self.smtppass, self.mailfrom, \ to_addrs, msg, d, heloFallback=True, requireAuthentication=False, \ - requireTransportSecurity=False) + requireTransportSecurity=self.smtptls) factory.noisy = False - reactor.connectTCP(self.smtphost, self.smtpport, factory) + + if self.smtpssl: + reactor.connectSSL(self.smtphost, self.smtpport, factory, ssl.ClientContextFactory()) + else: + reactor.connectTCP(self.smtphost, self.smtpport, factory) + return d