Example #1
0
def send_mail(from_addr, to_addr, file, host='localhost', port=25, timeout=60, retries=5,
             use_ssl=False, require_transport_security=None,
             require_authentication=None, username=None, password=None,
             helo_fallback=False):
    """ A utility function used to send email.

    :param from_addr: Sender email address.
    :param to_addr: Recipients email address.
    :param file: The full message, including headers. Any file-like or any object with
        a ``__str__`` can be used.

    :param host: Which SMTP server to use.
    :param port: Which port to connect to.

    :param use_ssl: Whether the server speaks SSL.
    :param require_transport_security: Whether to require transport security (TLS) before
        sending the email.

        Defaults to ``True`` if a username is specified.

        Defaults to ``False`` if using SSL due to `Twisted #3989
        <http://twistedmatrix.com/trac/ticket/3989>`_.

    :param require_authentication: Whether to login before sending an email.
        Defaults to ``True`` if a username is specified, ``False`` otherwise.
    :param username: The username used when logging in.
    :param password: The password used when logging in.

    :param timeout: Number of seconds to wait before timing out a connection.  If
        ``None``, perform no timeout checking.
    :param retries: Number of retries if we cannot connect to the server.

    :param helo_fallback: Whether to fallback to HELO if EHLO fails.

    """

    if hasattr(file, 'as_string'):
        # this looks like a email.message.Message
        file = StringIO(file.as_string())

    if not hasattr(file, 'read'):
        file = StringIO(str(file))

    if require_transport_security is None:
        if use_ssl:
            require_transport_security = False
        else:
            require_transport_security = username is not None

    if require_authentication is None:
        require_authentication = username is not None

    context_factory = None
    if use_ssl or require_transport_security:
        # only import the ssl module if required
        from twisted.internet import ssl
        context_factory = ssl.ClientContextFactory()

    deferred = defer.Deferred()

    sender_factory = smtp.ESMTPSenderFactory(
        contextFactory = context_factory,
        deferred = deferred,
        timeout = timeout,
        fromEmail = from_addr,
        toEmail = to_addr,
        file = file,
        retries = retries,
        requireTransportSecurity = require_transport_security,
        requireAuthentication = require_authentication,
        username = username,
        password = password,
        heloFallback = helo_fallback,
    )

    if use_ssl:
        reactor.connectSSL(host, port, sender_factory, context_factory)
    else:
        reactor.connectTCP(host, port, sender_factory)

    return deferred