Beispiel #1
0
    def test_email(config, recipient, subject, body, sender=None,
                   reply_to=None):
        """
        Sends an email via the SMTP Database Object

        :param config: The email configuration
        :type config: SMTPServer Database Model
        :param recipient: The recipients of the email
        :type recipient: list
        :param subject: The subject of the email
        :type subject: basestring
        :param body: The body of the email
        :type body: basestring
        :param sender: An optional sender of the email. The SMTP database
            object has its own sender. This parameter can be used to override
            the internal sender.
        :type sender: basestring
        :param reply_to: The Reply-To parameter
        :type reply_to: basestring
        :return: True or False
        """
        if type(recipient) != list:
            recipient = [recipient]
        mail_from = sender or config.sender
        reply_to = reply_to or mail_from
        msg = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
        msg['Subject'] = subject
        msg['From'] = mail_from
        msg['To'] = ",".join(recipient)
        msg['Date'] = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
        msg['Reply-To'] = reply_to

        mail = smtplib.SMTP(config.server, port=int(config.port),
                            timeout=TIMEOUT)
        mail.ehlo()
        # Start TLS if required
        if config.tls:
            log.debug("Trying to STARTTLS: {0!s}".format(config.tls))
            mail.starttls()
        # Authenticate, if a username is given.
        if config.username:
            log.debug("Doing authentication with {0!s}".format(config.username))
            password = decryptPassword(config.password)
            if password == FAILED_TO_DECRYPT_PASSWORD:
                password = config.password
            mail.login(config.username, password)
        r = mail.sendmail(mail_from, recipient, msg.as_string())
        log.info("Mail sent: {0!s}".format(r))
        # r is a dictionary like {"*****@*****.**": (200, 'OK')}
        # we change this to True or False
        success = True
        for one_recipient in recipient:
            res_id, res_text = r.get(one_recipient, (200, "OK"))
            if res_id != 200 and res_text != "OK":
                success = False
                log.error("Failed to send email to {0!s}: {1!s}, {2!s}".format(one_recipient,
                                                                  res_id,
                                                                  res_text))
        mail.quit()
        return success
Beispiel #2
0
def list_smtpservers(identifier=None, server=None):
    """
    This returns a list of all smtpservers matching the criterion.
    If no identifier or server is provided, it will return a list of all smtp
    server definitions.

    :param identifier: The identifier or the name of the SMTPServer definition.
        As the identifier is unique, providing an identifier will return a
        list with either one or no smtpserver
    :type identifier: basestring
    :param server: The FQDN or IP address of the smtpserver
    :type server: basestring
    :return: list of SMTPServer configuration dicts.
    """
    res = {}
    # get list of smtpserver objects
    server_obj_list = get_smtpservers(identifier=identifier, server=server)
    # transfer the definitions to a dictionary
    for server_obj in server_obj_list:
        decrypted_password = decryptPassword(server_obj.config.password)
        # If the database contains garbage, use the empty password as fallback
        if decrypted_password == FAILED_TO_DECRYPT_PASSWORD:
            decrypted_password = ""
        res[server_obj.config.identifier] = server_obj.config.get()
        res[server_obj.config.identifier].pop('id')
        res[server_obj.config.identifier].pop('identifier')
        res[server_obj.config.identifier].update({"password": decrypted_password})

    return res
Beispiel #3
0
    def test_01_encrypt_decrypt_pass(self):
        r = encryptPassword("passwörd")
        pin = decryptPassword(r)
        self.assertTrue(pin == "passwörd", (r, pin))

        r = encryptPassword(u"passwörd")
        pin = decryptPassword(r, convert_unicode=True)
        self.assertEqual(pin, u"passwörd")

        r = encryptPassword(u"passwörd")
        pin = decryptPassword(r, convert_unicode=False)
        self.assertEqual(pin, "passwörd")

        # error path returns the bytestring
        r = encryptPassword(b"\x01\x02\x03\x04")
        self.assertEqual(decryptPassword(r, convert_unicode=True), b"\x01\x02\x03\x04")
    def test_01_encrypt_decrypt_pass(self):
        r = encryptPassword("passwörd")
        pin = decryptPassword(r)
        self.assertTrue(pin == "passwörd", (r, pin))

        r = encryptPassword(u"passwörd")
        pin = decryptPassword(r, convert_unicode=True)
        self.assertEqual(pin, u"passwörd")

        r = encryptPassword(u"passwörd")
        pin = decryptPassword(r, convert_unicode=False)
        self.assertEqual(pin, "passwörd")

        # error path returns the bytestring
        r = encryptPassword(b"\x01\x02\x03\x04")
        self.assertEqual(decryptPassword(r, convert_unicode=True), b"\x01\x02\x03\x04")
Beispiel #5
0
def getResolverInfo(resolvername):
    '''
    return the resolver info of the given resolvername

    :param resolvername: the requested resolver
    :type  resolvername: string

    :return : dict of resolver description
    '''
    resolver_dict = {}
    typ = ""
    resolvertypes = get_resolver_types()

    descr = {}

    conf = get_privacyIDEA_config()

    for entry in conf:

        for typ in resolvertypes:

            ## get the typed values of the descriptor!
            resolver_conf = get_resolver_classConfig(typ)
            if typ in resolver_conf:
                descr = resolver_conf.get(typ).get('config', {})
            else:
                descr = resolver_conf

            if entry.startswith("privacyidea." + typ) and entry.endswith(resolvername):
                #the realm might contain dots "."
                # so take all after the 3rd dot for realm
                resolver = entry.split(".", 3)
                # An old entry without resolver name
                if len(resolver) <= 3:
                    break

                value = conf.get(entry)
                if resolver[2] in descr:
                    configEntry = resolver[2]
                    if descr.get(configEntry) == 'password':

                        ## do we already have the decrypted pass?
                        if 'enc' + entry in conf:
                            value = conf.get('enc' + entry)
                        else:
                            ## if no, we take the encpass and decrypt it
                            value = conf.get(entry)
                            try:
                                en = decryptPassword(value)
                                value = en
                            except:
                                log.info("Decryption of resolver passwd failed: compatibility issue?")

                resolver_dict[ resolver[2] ] = value
                # Dont check the other resolver types

                break

    return { "type" : typ, "data" : resolver_dict, "resolver" : resolvername}
    def test_01_encrypt_decrypt_pass(self):
        r = encryptPassword(u"passwörd".encode('utf8'))
        # encryptPassword returns unicode
        self.assertTrue(isinstance(r, text_type))
        pin = decryptPassword(r)
        # decryptPassword always returns unicode
        self.assertEqual(pin, u"passwörd")

        r = encryptPassword(u"passwörd")
        pin = decryptPassword(r)
        self.assertEqual(pin, u"passwörd")

        # decrypt some passwords generated with 2.23
        pw1 = '3d1bf9db4c75469b4bb0bc7c70133181:2c27ac3839ed2213b8399d0471b17136'
        self.assertEqual(decryptPassword(pw1), 'test123')
        pw2 = '3a1be65a234f723fe5c6969b818582e1:08e51d1c65aa74c4988d094c40cb972c'
        self.assertEqual(decryptPassword(pw2), 'test123')
        pw3 = '7a4d5e2f26978394e33715bc3e8188a3:90b2782112ad7bbc5b48bd10e5c7c096cfe4ef7d9d11272595dc5b6c7f21d98a'
        self.assertEqual(decryptPassword(pw3, ), u'passwörd')

        # TODO: add checks for broken paddings/encrypted values and malformed enc_data

        not_valid_password = b"\x01\x02\x03\x04\xff"
        r = encryptPassword(not_valid_password)
        # A non valid password will raise an exception during decryption
        self.assertEqual(decryptPassword(r), 'FAILED TO DECRYPT PASSWORD!')

        # A value with missing colon (IV) will fail to decrypt
        self.assertEqual(decryptPassword('test'),
                         'FAILED TO DECRYPT PASSWORD!')
    def test_01_encrypt_decrypt_pass(self):
        r = encryptPassword(u"passwörd".encode('utf8'))
        # encryptPassword returns unicode
        self.assertTrue(isinstance(r, text_type))
        pin = decryptPassword(r)
        # decryptPassword always returns unicode
        self.assertEqual(pin, u"passwörd")

        r = encryptPassword(u"passwörd")
        pin = decryptPassword(r)
        self.assertEqual(pin, u"passwörd")

        # decrypt some passwords generated with 2.23
        pw1 = '3d1bf9db4c75469b4bb0bc7c70133181:2c27ac3839ed2213b8399d0471b17136'
        self.assertEqual(decryptPassword(pw1), 'test123')
        pw2 = '3a1be65a234f723fe5c6969b818582e1:08e51d1c65aa74c4988d094c40cb972c'
        self.assertEqual(decryptPassword(pw2), 'test123')
        pw3 = '7a4d5e2f26978394e33715bc3e8188a3:90b2782112ad7bbc5b48bd10e5c7c096cfe4ef7d9d11272595dc5b6c7f21d98a'
        self.assertEqual(decryptPassword(pw3, ), u'passwörd')

        # TODO: add checks for broken paddings/encrypted values and malformed enc_data

        not_valid_password = b"\x01\x02\x03\x04\xff"
        r = encryptPassword(not_valid_password)
        # A non valid password will raise an exception during decryption
        self.assertEqual(decryptPassword(r), 'FAILED TO DECRYPT PASSWORD!')

        # A value with missing colon (IV) will fail to decrypt
        self.assertEqual(decryptPassword('test'), 'FAILED TO DECRYPT PASSWORD!')
    def test_01_encrypt_decrypt_pass(self):
        r = encryptPassword(u"passwörd".encode('utf8'))
        # encryptPassword returns unicode
        self.assertTrue(isinstance(r, text_type))
        pin = decryptPassword(r)
        # decryptPassword always returns unicode
        self.assertEqual(pin, u"passwörd")

        r = encryptPassword(u"passwörd")
        pin = decryptPassword(r)
        self.assertEqual(pin, u"passwörd")

        not_valid_password = b"\x01\x02\x03\x04\xff"
        r = encryptPassword(not_valid_password)
        # A non valid password will raise an exception during decryption
        self.assertEqual(decryptPassword(r), 'FAILED TO DECRYPT PASSWORD!')

        # A value with missing colon (IV) will fail to decrypt
        self.assertEqual(decryptPassword('test'), 'FAILED TO DECRYPT PASSWORD!')
Beispiel #9
0
    def test_01_encrypt_decrypt_pass(self):
        r = encryptPassword(u"passwörd".encode('utf8'))
        pin = decryptPassword(r)
        self.assertEqual(pin, u"passwörd".encode('utf8'))

        r = encryptPassword(u"passwörd")
        pin = decryptPassword(r, convert_unicode=True)
        self.assertEqual(pin, u"passwörd")

        r = encryptPassword(u"passwörd")
        pin = decryptPassword(r, convert_unicode=False)
        self.assertEqual(pin, u"passwörd".encode('utf8'))

        # error path returns the bytestring
        bs = b"\x01\x02\x03\x04\xff"
        r = encryptPassword(bs)
        self.assertEqual(decryptPassword(r, convert_unicode=True), bs)

        self.assertEqual(decryptPassword('test'), 'FAILED TO DECRYPT PASSWORD!')
Beispiel #10
0
    def test_email(config, recipient, subject, body, sender=None):
        """
        Sends an email via the SMTP Database Object

        :param config: The email configuration
        :type config: SMTPServer Database Model
        :param recipient: The recipients of the email
        :type recipient: list
        :param subject: The subject of the email
        :type subject: basestring
        :param body: The body of the email
        :type body: basestring
        :param sender: An optional sender of the email. The SMTP database
            object has its own sender. This parameter can be used to override
            the internal sender.
        :type sender: basestring
        :return: True or False
        """
        if type(recipient) != list:
            recipient = [recipient]
        mail_from = sender or config.sender
        msg = MIMEText(body)
        msg['Subject'] = subject
        msg['From'] = mail_from
        msg['To'] = ",".join(recipient)
        msg['Date'] = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())

        mail = smtplib.SMTP(config.server, port=int(config.port))
        mail.ehlo()
        # Start TLS if required
        if config.tls:
            log.debug("Trying to STARTTLS: {0!s}".format(config.tls))
            mail.starttls()
        # Authenticate, if a username is given.
        if config.username:
            log.debug("Doing authentication with {0!s}".format(config.username))
            password = decryptPassword(config.password)
            if password == FAILED_TO_DECRYPT_PASSWORD:
                password = config.password
            mail.login(config.username, password)
        r = mail.sendmail(mail_from, recipient, msg.as_string())
        log.info("Mail sent: {0!s}".format(r))
        # r is a dictionary like {"*****@*****.**": (200, 'OK')}
        # we change this to True or False
        success = True
        for one_recipient in recipient:
            res_id, res_text = r.get(one_recipient, (200, "OK"))
            if res_id != 200 and res_text != "OK":
                success = False
                log.error("Failed to send email to {0!s}: {1!s}, {2!s}".format(one_recipient,
                                                                  res_id,
                                                                  res_text))
        mail.quit()
        return success
    def test_email(config, recipient, subject, body, sender=None):
        """
        Sends an email via the SMTP Database Object

        :param config: The email configuration
        :type config: SMTPServer Database Model
        :param recipient: The recipients of the email
        :type recipient: list
        :param subject: The subject of the email
        :type subject: basestring
        :param body: The body of the email
        :type body: basestring
        :param sender: An optional sender of the email. The SMTP database
            object has its own sender. This parameter can be used to override
            the internal sender.
        :type sender: basestring
        :return: True or False
        """
        mail_from = sender or config.sender
        date = datetime.datetime.utcnow().strftime("%c")
        body = """From: %s
Subject: %s
Date: %s

%s""" % (mail_from, subject, date, body)

        mail = smtplib.SMTP(config.server, port=int(config.port))
        mail.ehlo()
        # Start TLS if required
        if config.tls:
            log.debug("Trying to STARTTLS: %s" % config.tls)
            mail.starttls()
        # Authenticate, if a username is given.
        if config.username:
            log.debug("Doing authentication with %s" % config.username)
            password = decryptPassword(config.password)
            mail.login(config.username, password)
        r = mail.sendmail(mail_from, recipient, body)
        log.info("Mail sent: %s" % r)
        # r is a dictionary like {"*****@*****.**": (200, 'OK')}
        # we change this to True or False
        if type(recipient) != list:
            recipient = [recipient]
        success = True
        for one_recipient in recipient:
            res_id, res_text = r.get(one_recipient, (200, "OK"))
            if res_id != 200 and res_text != "OK":
                success = False
                log.error("Failed to send email to %s: %s, %s" % (recipient,
                                                                  res_id,
                                                                  res_text))
        mail.quit()
        return success
Beispiel #12
0
    def test_email(config, recipient, subject, body, sender=None):
        """
        Sends an email via the SMTP Database Object

        :param config: The email configuration
        :type config: SMTPServer Database Model
        :param recipient: The recipients of the email
        :type recipient: list
        :param subject: The subject of the email
        :type subject: basestring
        :param body: The body of the email
        :type body: basestring
        :param sender: An optional sender of the email. The SMTP database
            object has its own sender. This parameter can be used to override
            the internal sender.
        :type sender: basestring
        :return: True or False
        """
        mail_from = sender or config.sender
        date = datetime.datetime.utcnow().strftime("%c")
        body = """From: %s
Subject: %s
Date: %s

%s""" % (mail_from, subject, date, body)

        mail = smtplib.SMTP(config.server, port=int(config.port))
        mail.ehlo()
        # Start TLS if required
        if config.tls:
            log.debug("Trying to STARTTLS: %s" % config.tls)
            mail.starttls()
        # Authenticate, if a username is given.
        if config.username:
            log.debug("Doing authentication with %s" % config.username)
            password = decryptPassword(config.password)
            mail.login(config.username, password)
        r = mail.sendmail(mail_from, recipient, body)
        log.info("Mail sent: %s" % r)
        # r is a dictionary like {"*****@*****.**": (200, 'OK')}
        # we change this to True or False
        if type(recipient) != list:
            recipient = [recipient]
        success = True
        for one_recipient in recipient:
            res_id, res_text = r.get(one_recipient, (200, "OK"))
            if res_id != 200 and res_text != "OK":
                success = False
                log.error("Failed to send email to %s: %s, %s" %
                          (recipient, res_id, res_text))
        mail.quit()
        return success
Beispiel #13
0
    def request(config, user, password):
        """
        Perform a RADIUS request to a RADIUS server.
        The RADIUS configuration contains the IP address, the port and the
        secret of the RADIUS server.

        * config.server
        * config.port
        * config.secret

        :param config: The RADIUS configuration
        :type config: RADIUSServer Database Model
        :param user: the radius username
        :param password: the radius password
        :return: True or False. If any error occurs, an exception is raised.
        """
        success = False

        nas_identifier = get_from_config("radius.nas_identifier",
                                         "privacyIDEA")
        r_dict = config.dictionary or get_from_config("radius.dictfile",
                                                      "/etc/privacyidea/"
                                                      "dictionary")
        log.debug("NAS Identifier: %r, "
                  "Dictionary: %r" % (nas_identifier, r_dict))
        log.debug("constructing client object "
                  "with server: %r, port: %r, secret: %r" %
                  (config.server, config.port, config.secret))

        srv = Client(server=config.server,
                     authport=config.port,
                     secret=decryptPassword(config.secret),
                     dict=Dictionary(r_dict))

        req = srv.CreateAuthPacket(code=pyrad.packet.AccessRequest,
                                   User_Name=user.encode('ascii'),
                                   NAS_Identifier=nas_identifier.encode('ascii'))

        req["User-Password"] = req.PwCrypt(password)
        response = srv.SendPacket(req)
        if response.code == pyrad.packet.AccessAccept:
            log.info("Radiusserver %s granted "
                     "access to user %s." % (config.server, user))
            success = True
        else:
            log.warning("Radiusserver %s"
                        "rejected access to user %s." %
                        (config.server, user))

        return success
Beispiel #14
0
    def request(config, user, password):
        """
        Perform a RADIUS request to a RADIUS server.
        The RADIUS configuration contains the IP address, the port and the
        secret of the RADIUS server.

        * config.server
        * config.port
        * config.secret

        :param config: The RADIUS configuration
        :type config: RADIUSServer Database Model
        :param user: the radius username
        :param password: the radius password
        :return: True or False. If any error occurs, an exception is raised.
        """
        success = False

        nas_identifier = get_from_config("radius.nas_identifier",
                                         "privacyIDEA")
        r_dict = config.dictionary or get_from_config(
            "radius.dictfile", "/etc/privacyidea/"
            "dictionary")
        log.debug("NAS Identifier: %r, "
                  "Dictionary: %r" % (nas_identifier, r_dict))
        log.debug("constructing client object "
                  "with server: %r, port: %r, secret: %r" %
                  (config.server, config.port, config.secret))

        srv = Client(server=config.server,
                     authport=config.port,
                     secret=decryptPassword(config.secret),
                     dict=Dictionary(r_dict))

        req = srv.CreateAuthPacket(
            code=pyrad.packet.AccessRequest,
            User_Name=user.encode('ascii'),
            NAS_Identifier=nas_identifier.encode('ascii'))

        req["User-Password"] = req.PwCrypt(password)
        response = srv.SendPacket(req)
        if response.code == pyrad.packet.AccessAccept:
            log.info("Radiusserver %s granted "
                     "access to user %s." % (config.server, user))
            success = True
        else:
            log.warning("Radiusserver %s"
                        "rejected access to user %s." % (config.server, user))

        return success
Beispiel #15
0
def list_radiusservers(identifier=None, server=None):
    res = {}
    server_list = get_radiusservers(identifier=identifier, server=server)
    for server in server_list:
        decrypted_password = decryptPassword(server.config.secret)
        # If the database contains garbage, use the empty password as fallback
        if decrypted_password == FAILED_TO_DECRYPT_PASSWORD:
            decrypted_password = ""
        res[server.config.identifier] = {
            "server": server.config.server,
            "port": server.config.port,
            "dictionary": server.config.dictionary,
            "description": server.config.description,
            "password": decrypted_password,
            "timeout": server.config.timeout,
            "retries": server.config.retries
        }

    return res
Beispiel #16
0
def _retrieveAllConfigDB():

    config = {}
    delay = False
    for conf in Session.query(Config).all():
        log.debug("key %r:%r" % (conf.Key, conf.Value))
        key = conf.Key
        if (not key.startswith("privacyidea.")):
            key = "privacyidea." + conf.Key
        nVal = _expandHere(conf.Value)
        config[key] = nVal
        myTyp = conf.Type
        if myTyp is not None:
            if myTyp == 'password':
                if hasattr(c, 'hsm') == True and isinstance(c.hsm, dict):
                    hsm = c.hsm.get('obj')
                    if hsm is not None and hsm.isReady() == True:
                        config['enc' + key] = decryptPassword(conf.Value)
                else:
                    delay = True

    return (config, delay)
Beispiel #17
0
def _storeConfigDB(key, val, typ=None, desc=None):
    value = val

    if (not key.startswith("privacyidea.")):
        key = "privacyidea." + key

    confEntries = Session.query(Config).filter(Config.Key == unicode(key))
    theConf = None

    if typ is not None and typ == 'password':
        value = encryptPassword(val)
        en = decryptPassword(value)
        if (en != val):
            raise Exception("StoreConfig: Error during encoding password type!")

    ## update
    if confEntries.count() == 1:
        theConf = confEntries[0]
        theConf.Value = unicode(value)
        if (typ is not None):
            theConf.Type = unicode(typ)
        if (desc is not None):
            theConf.Description = unicode(desc)

    ## insert
    elif confEntries.count() == 0:
        theConf = Config(
                        Key=unicode(key),
                        Value=unicode(value),
                        Type=unicode(typ),
                        Description=unicode(desc)
                        )
    if theConf is not None:
        Session.add(theConf)

    return 101
 def get_secret(self):
     return decryptPassword(self.config.secret)
Beispiel #19
0
 def get_secret(self):
     return decryptPassword(self.config.secret)
Beispiel #20
0
    def test_email(config,
                   recipient,
                   subject,
                   body,
                   sender=None,
                   reply_to=None,
                   mimetype="plain"):
        """
        Sends an email via the configuration.

        :param config: The email configuration
        :type config: dict
        :param recipient: The recipients of the email
        :type recipient: list
        :param subject: The subject of the email
        :type subject: basestring
        :param body: The body of the email
        :type body: basestring
        :param sender: An optional sender of the email. The SMTP database
            object has its own sender. This parameter can be used to override
            the internal sender.
        :type sender: basestring
        :param reply_to: The Reply-To parameter
        :type reply_to: basestring
        :param mimetype: The type of the email to send. Can by plain or html
        :return: True or False
        """
        if type(recipient) != list:
            recipient = [recipient]
        mail_from = sender or config['sender']
        reply_to = reply_to or mail_from
        msg = MIMEText(body.encode('utf-8'), mimetype, 'utf-8')
        msg['Subject'] = subject
        msg['From'] = mail_from
        msg['To'] = ",".join(recipient)
        msg['Date'] = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
        msg['Reply-To'] = reply_to

        mail = smtplib.SMTP(config['server'],
                            port=int(config['port']),
                            timeout=config.get('timeout', TIMEOUT))
        log.debug(u"submitting message to {0!s}".format(msg["To"]))
        log.debug("Saying EHLO to mailserver {0!s}".format(config['server']))
        r = mail.ehlo()
        log.debug("mailserver responded with {0!s}".format(r))
        # Start TLS if required
        if config.get('tls', False):
            log.debug("Trying to STARTTLS: {0!s}".format(config['tls']))
            mail.starttls()
        # Authenticate, if a username is given.
        if config.get('username', ''):
            log.debug("Doing authentication with {0!s}".format(
                config['username']))
            password = decryptPassword(config['password'])
            if password == FAILED_TO_DECRYPT_PASSWORD:
                password = config['password']
            # Under Python 2, we pass passwords as bytestrings to get CRAM-MD5 to work.
            # We add a safeguard config option to disable the conversion.
            # Under Python 3, we pass passwords as unicode.
            if six.PY2 and get_app_config_value("PI_SMTP_PASSWORD_AS_BYTES",
                                                True):
                password = to_bytes(password)
            mail.login(config['username'], password)
        r = mail.sendmail(mail_from, recipient, msg.as_string())
        log.info("Mail sent: {0!s}".format(r))
        # r is a dictionary like {"*****@*****.**": (200, 'OK')}
        # we change this to True or False
        success = True
        for one_recipient in recipient:
            res_id, res_text = r.get(one_recipient, (200, "OK"))
            if res_id != 200 and res_text != "OK":
                success = False
                log.error("Failed to send email to {0!r}: {1!r}, {2!r}".format(
                    one_recipient, res_id, res_text))
        mail.quit()
        log.debug("I am done sending your email.")
        return success
 def test_01_encrypt_decrypt_pass(self):
     r = encryptPassword("passwörd")
     pin = decryptPassword(r)
     self.assertTrue(pin == "passwörd", (r, pin))
Beispiel #22
0
    def test_email(config, recipient, subject, body, sender=None,
                   reply_to=None, mimetype="plain"):
        """
        Sends an email via the configuration.

        :param config: The email configuration
        :type config: dict
        :param recipient: The recipients of the email
        :type recipient: list
        :param subject: The subject of the email
        :type subject: basestring
        :param body: The body of the email
        :type body: basestring
        :param sender: An optional sender of the email. The SMTP database
            object has its own sender. This parameter can be used to override
            the internal sender.
        :type sender: basestring
        :param reply_to: The Reply-To parameter
        :type reply_to: basestring
        :param mimetype: The type of the email to send. Can by plain or html
        :return: True or False
        """
        if type(recipient) != list:
            recipient = [recipient]
        mail_from = sender or config['sender']
        reply_to = reply_to or mail_from
        msg = MIMEText(body.encode('utf-8'), mimetype, 'utf-8')
        msg['Subject'] = subject
        msg['From'] = mail_from
        msg['To'] = ",".join(recipient)
        msg['Date'] = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
        msg['Reply-To'] = reply_to

        mail = smtplib.SMTP(config['server'], port=int(config['port']),
                            timeout=config.get('timeout', TIMEOUT))
        log.debug(u"submitting message to {0!s}".format(msg["To"]))
        log.debug("Saying EHLO to mailserver {0!s}".format(config['server']))
        r = mail.ehlo()
        log.debug("mailserver responded with {0!s}".format(r))
        # Start TLS if required
        if config.get('tls', False):
            log.debug("Trying to STARTTLS: {0!s}".format(config['tls']))
            mail.starttls()
        # Authenticate, if a username is given.
        if config.get('username', ''):
            log.debug("Doing authentication with {0!s}".format(config['username']))
            password = decryptPassword(config['password'])
            if password == FAILED_TO_DECRYPT_PASSWORD:
                password = config['password']
            # Under Python 2, we pass passwords as bytestrings to get CRAM-MD5 to work.
            # We add a safeguard config option to disable the conversion.
            # Under Python 3, we pass passwords as unicode.
            if six.PY2 and get_app_config_value("PI_SMTP_PASSWORD_AS_BYTES", True):
                password = to_bytes(password)
            mail.login(config['username'], password)
        r = mail.sendmail(mail_from, recipient, msg.as_string())
        log.info("Mail sent: {0!s}".format(r))
        # r is a dictionary like {"*****@*****.**": (200, 'OK')}
        # we change this to True or False
        success = True
        for one_recipient in recipient:
            res_id, res_text = r.get(one_recipient, (200, "OK"))
            if res_id != 200 and res_text != "OK":
                success = False
                log.error("Failed to send email to {0!r}: {1!r}, {2!r}".format(one_recipient,
                                                                  res_id,
                                                                  res_text))
        mail.quit()
        log.debug("I am done sending your email.")
        return success