예제 #1
0
    def _mint_pid(obj, dummy_eng):
        d = Deposition(obj)
        recjson = d.get_latest_sip(sealed=False).metadata

        if 'recid' not in recjson:
            raise Exception("'recid' not found in sip metadata.")

        pid_text = None
        pid = recjson.get(pid_field, None)
        if not pid:
            # No pid found in recjson, so create new pid with user supplied
            # function.
            pid_text = recjson[pid_field] = pid_creator(recjson)
        else:
            # Pid found - check if it should be minted
            if existing_pid_checker and existing_pid_checker(pid, recjson):
                pid_text = pid

        # Create an assign pid internally - actually registration will happen
        # asynchronously later.
        if pid_text:
            current_app.logger.info("Registering pid %s" % pid_text)
            pid_obj = PersistentIdentifier.create(pid_store_type, pid_text)
            if pid_obj is None:
                pid_obj = PersistentIdentifier.get(pid_store_type, pid_text)

            try:
                pid_obj.assign("rec", recjson['recid'])
            except Exception:
                register_exception(alert_admin=True)

        d.update()
예제 #2
0
        def __call__(self, environ, start_response):
            """Wrapper for legacy calls."""
            with self.app.request_context(environ):
                g.start_response = start_response
                try:
                    response = self.app.full_dispatch_request()
                except Exception as e:
                    from invenio_ext.logging import register_exception
                    register_exception(req=request, alert_admin=True)
                    response = self.app.handle_exception(e)

                return response(environ, start_response)
예제 #3
0
 def get_formatted_data(self, **kwargs):
     """Get the formatted representation for this object."""
     from .registry import workflows
     try:
         name = self.get_workflow_name()
         if not name:
             return "Did not find any way to format data."
         workflow_definition = workflows[name]
         formatted_data = workflow_definition.formatter(
             self,
             **kwargs
         )
     except (KeyError, AttributeError) as err:
         # Somehow the workflow or formatter does not exist
         from invenio_ext.logging import register_exception
         register_exception(alert_admin=True)
         formatted_data = "Error formatting record: {0}".format(err)
     return formatted_data
예제 #4
0
 def get_formatted_data(self, of=None):
     """Get the formatted representation for this object."""
     from .registry import workflows
     if of is None:
         of = cfg.get("WORKFLOWS_HOLDING_PEN_DEFAULT_OUTPUT_FORMAT")
     try:
         name = self.get_workflow_name()
         if not name:
             return ""
         workflow_definition = workflows[name]
         formatted_data = workflow_definition.formatter(
             self,
             of=of
         )
     except (KeyError, AttributeError):
         # Somehow the workflow or formatter does not exist
         from invenio_ext.logging import register_exception
         register_exception(alert_admin=True)
         formatted_data = ""
     return formatted_data
예제 #5
0
    def __call__(self, req, form):
        """Return deprecation warning."""
        try:
            from invenio.legacy.webpage import page
        except ImportError:
            register_exception()

            def page(*args):
                return args[1]
        req.status = apache.HTTP_SERVICE_UNAVAILABLE
        msg = "<p>This functionality will be soon deprecated.</p>"
        try:
            from invenio.config import CFG_SITE_ADMIN_EMAIL
            msg += """<p>If you would still like to use it, please ask your
                Invenio administrator <code>%s</code> to consider enabling it.
                </p>""" % CFG_SITE_ADMIN_EMAIL
        except ImportError:
            pass
        try:
            return page('Service disabled', msg, req=req)
        except Exception:
            return msg
예제 #6
0
    def __call__(self, req, form):
        try:
            from invenio.legacy.webpage import page
        except ImportError:
            register_exception()

            def page(*args):
                return args[1]
        req.status = apache.HTTP_SERVICE_UNAVAILABLE
        msg = ("<p>This functionality is currently unavailable due to "
               "a service maintenance.</p>")
        try:
            from invenio.config import CFG_SITE_ADMIN_EMAIL
            msg += ("<p>You can contact <code>%s</code> "
                    "in case of questions.</p>" % CFG_SITE_ADMIN_EMAIL)
        except ImportError:
            pass
        msg += """<p>We are going to restore the service soon.</p>
                  <p>Sorry for the inconvenience.</p>"""
        try:
            return page('Service unavailable', msg, req=req)
        except Exception:
            return msg
예제 #7
0
    def calculate_RFC2104_HMAC(data, _amazon_secret_access_key):
        """
        Computes a RFC 2104 compliant HMAC Signature and then Base64
        encodes it.

        Module hashlib must be installed if Python < 2.5
        <http://pypi.python.org/pypi/hashlib/20081119>

        @param data: data to sign
        @param _amazon_secret_access_key: your Amazon secret key

        @type data: string
        @type _amazon_secret_access_key: string. Empty if hashlib module not installed
        """
        if not HASHLIB_IMPORTED:
            try:
                raise Exception(
                    "Module hashlib not installed. Please install it.")
            except:
                from invenio_ext.logging import register_exception
                register_exception(
                    stream='warning',
                    alert_admin=True,
                    subject='Cannot create AWS signature')
                return ""
        else:
            if sys.version_info < (2, 5):
                # compatibility mode for Python < 2.5 and hashlib
                my_digest_algo = _MySHA256(sha256())
            else:
                my_digest_algo = sha256

        return base64.encodestring(
            hmac.new(
                _amazon_secret_access_key,
                data,
                my_digest_algo).digest()).strip()
예제 #8
0
def acc_firerole_check_user(user_info, firerole_def_obj):
    """Matche the rules inside the deserialized compiled definition.

    Given a user_info dictionary, it matches the rules inside the deserialized
    compiled definition in order to discover if the current user match the roles
    corresponding to this definition.
    :param user_info: a dict produced by UserInfo(uid) which contains every
    info about a user
    :param firerole_def_obj: a compiled deserialized definition produced by
    compile_role_defintion
    :return: True if the user match the definition, False otherwise.
    """
    try:
        default_allow_p, rules = firerole_def_obj
        # for every rule
        for (allow_p, not_p, field, expressions_list) in rules:
            group_p = field == 'group'  # Is it related to group?
            ip_p = field == 'remote_ip'  # Is it related to Ips?
            until_p = field == 'until'  # Is it related to dates?
            from_p = field == 'from'  # Idem.
            next_expr_p = False  # Silly flag to break 2 for cycles
            if field not in user_info and not from_p and not until_p:
                continue
            # For every element in the rule
            for reg_p, expr in expressions_list:
                if group_p:  # Special case: groups
                    if reg_p:  # When it is a regexp
                        # iterate over every group
                        for group in user_info[field]:
                            if expr.match(group):  # if it matches
                                if not_p:  # if must not match
                                    # let's skip to next expr
                                    next_expr_p = True
                                    break
                                else:  # Ok!
                                    return allow_p
                        if next_expr_p:
                            break  # I said: let's skip to next rule ;-)
                    # Simple expression then just check for expr in groups
                    elif expr.lower() in [
                            group.lower() for group in user_info[field]
                    ]:
                        # If expr is in groups then if must not match
                        if not_p:
                            break  # let's skip to next expr
                        else:  # Ok!
                            return allow_p
                elif reg_p:  # Not a group, then easier. If it's a regexp
                    if expr.match(user_info[field]):  # if it matches
                        if not_p:  # If must not match
                            break  # Let's skip to next expr
                        else:
                            return allow_p  # Ok!
                # If it's just a simple expression but an IP!
                elif ip_p and isinstance(expr, tuple):
                    # Then if Ip matches
                    if _ipmatch(user_info['remote_ip'], expr):
                        if not_p:  # If must not match
                            break  # let's skip to next expr
                        else:
                            return allow_p  # ok!
                elif until_p:
                    if time.time() <= expr:
                        if allow_p:
                            break
                        else:
                            return False
                    elif allow_p:
                        return False
                    else:
                        break
                elif from_p:
                    if time.time() >= expr:
                        if allow_p:
                            break
                        else:
                            return False
                    elif allow_p:
                        return False
                    else:
                        break
                # Finally the easiest one!!
                elif expr.lower() == str(user_info[field]).lower():
                    if not_p:  # ...
                        break
                    else:  # ...
                        return allow_p  # ...
            if not_p and not next_expr_p:  # Nothing has matched and we got not
                return allow_p  # Then the whole rule matched!
    except Exception as msg:
        register_exception(alert_admin=True)
        raise InvenioWebAccessFireroleError(msg)
    return default_allow_p  # By default we allow ;-) it'an OpenAccess project
예제 #9
0
def create_Indico_request_url(
        base_url,
        indico_what,
        indico_loc,
        indico_id,
        indico_type,
        indico_params,
        indico_key,
        indico_sig,
        _timestamp=None):
    """
    Create a signed Indico request URL to access Indico HTTP Export APIs.

    See U{http://indico.cern.ch/ihelp/html/ExportAPI/index.html} for more
    information.

    Example:
    >> create_Indico_request_url("https://indico.cern.ch",
                                 "categ",
                                 "",
                                 [1, 7],
                                 "xml",
                                 {'onlypublic': 'yes',
                                  'order': 'title',
                                  'from': 'today',
                                  'to': 'tomorrow'},
                                 '00000000-0000-0000-0000-000000000000',
                                 '00000000-0000-0000-0000-000000000000')

    @param base_url: Service base URL of the Indico instance to query
    @param indico_what: element to export
    @type indico_what: one of the strings: C{categ}, C{event}, C{room}, C{reservation}
    @param indico_loc: location of the element(s) specified by ID (only used for some elements)
    @param indico_id: ID of the element to be exported
    @type indico_id: a string or a list/tuple of strings
    @param indico_type: output format
    @type indico_type: one of the strings: C{json}, C{jsonp}, C{xml}, C{html}, C{ics}, C{atom}
    @param indico_params: parameters of the query. See U{http://indico.cern.ch/ihelp/html/ExportAPI/common.html}
    @param indico_key: API key provided for the given Indico instance
    @param indico_sig: API secret key (signature) provided for the given Indico instance
    @param _timestamp: for testing purpose only (default: current timestamp)

    @return signed URL of the request (string)
    """

    url = '/export/' + indico_what + '/'
    if indico_loc:
        url += indico_loc + '/'
    if type(indico_id) in (list, tuple):
        # dash separated list of values
        indico_id = '-'.join([str(x) for x in indico_id])
    url += indico_id + '.' + str(indico_type)

    if hasattr(indico_params, 'items'):
        items = indico_params.items()
    else:
        items = list(indico_params)
    if indico_key:
        items.append(('apikey', indico_key))
    if indico_sig and HASHLIB_IMPORTED:
        if _timestamp:
            items.append(('timestamp', str(_timestamp)))
        else:
            items.append(('timestamp', str(int(time.time()))))
        items = sorted(items, key=lambda x: x[0].lower())
        url_to_sign = '%s?%s' % (url, urlencode(items))
        if sys.version_info < (2, 5):
            # compatibility mode for Python < 2.5 and hashlib
            my_digest_algo = _MySHA1(sha1())
        else:
            my_digest_algo = sha1
        signature = hmac.new(indico_sig, url_to_sign,
                             my_digest_algo).hexdigest()
        items.append(('signature', signature))
    elif not HASHLIB_IMPORTED:
        try:
            raise Exception("Module hashlib not installed. Please install it.")
        except:
            from invenio_ext.logging import register_exception
            register_exception(stream='warning', alert_admin=True,
                               subject='Cannot create AWS signature')
    if not items:
        return url

    url = '%s%s?%s' % (base_url.strip('/'), url, urlencode(items))
    return url
예제 #10
0
def main():
    """Main function that analyzes command line input and calls whatever
    is appropriate. """

    from invenio_access.firerole import repair_role_definitions
    from invenio_access.control import (acc_add_default_settings,
                                                acc_reset_default_settings)
    from invenio_base.globals import cfg

    DEF_DEMO_USER_ROLES = cfg.get('DEF_DEMO_USER_ROLES', tuple())
    DEF_DEMO_ROLES = cfg.get('DEF_DEMO_ROLES', tuple())
    DEF_DEMO_AUTHS = cfg.get('DEF_DEMO_AUTHS', tuple())

    ## parse command line:
    # set user-defined options:
    options = {'user' : '', 'reset' : 0, 'compile' : 0, 'add' : 0, 'demo' : 0}
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hVu:racD",
                                    ["help", "version", "user="******"reset", "add", "compile", "demo"])
    except getopt.GetoptError as err:
        usage(1, err)
    try:
        for opt in opts:
            if opt[0] in ("-h", "--help"):
                usage(0)
            elif opt[0] in ("-V", "--version"):
                print(__revision__)
                sys.exit(0)
            elif opt[0] in ("-u", "--user"):
                options["user"] = opt[1]
            elif opt[0] in ("-r", "--reset"):
                options["reset"] = 1
            elif opt[0] in ("-a", "--add"):
                options["add"] = 1
            elif opt[0] in ("-c", "--compile"):
                options["compile"] = 1
            elif opt[0] in ("-D", "--demo"):
                options["demo"] = 1
            else:
                usage(1)
        if options['add'] or options['reset'] or options['compile']:
            #if acca.acc_get_action_id('cfgwebaccess'):
            #    # Action exists hence authentication works :-)
            #    options['user'] = authenticate(options['user'],
            #        authorization_msg="WebAccess Administration",
            #        authorization_action="cfgwebaccess")
            if options['reset'] and options['demo']:
                acc_reset_default_settings(
                    [cfg['CFG_SITE_ADMIN_EMAIL']], DEF_DEMO_USER_ROLES,
                    DEF_DEMO_ROLES, DEF_DEMO_AUTHS)
                print("Reset default demo site settings.")
            elif options['reset']:
                acc_reset_default_settings([cfg['CFG_SITE_ADMIN_EMAIL']])
                print("Reset default settings.")
            elif options['add'] and options['demo']:
                acc_add_default_settings(
                    [cfg['CFG_SITE_ADMIN_EMAIL']], DEF_DEMO_USER_ROLES,
                    DEF_DEMO_ROLES, DEF_DEMO_AUTHS)
                print("Added default demo site settings.")
            elif options['add']:
                acc_add_default_settings([cfg['CFG_SITE_ADMIN_EMAIL']])
                print("Added default settings.")
            if options['compile']:
                repair_role_definitions()
                print("Compiled firewall like role definitions.")
        else:
            usage(1, "You must specify at least one command")
    except StandardError as e:
        from invenio_ext.logging import register_exception
        register_exception()
        usage(e)
    return
예제 #11
0
def acc_firerole_check_user(user_info, firerole_def_obj):
    """Matche the rules inside the deserialized compiled definition.

    Given a user_info dictionary, it matches the rules inside the deserialized
    compiled definition in order to discover if the current user match the roles
    corresponding to this definition.
    :param user_info: a dict produced by UserInfo(uid) which contains every
    info about a user
    :param firerole_def_obj: a compiled deserialized definition produced by
    compile_role_defintion
    :return: True if the user match the definition, False otherwise.
    """
    try:
        default_allow_p, rules = firerole_def_obj
        # for every rule
        for (allow_p, not_p, field, expressions_list) in rules:
            group_p = field == 'group'  # Is it related to group?
            ip_p = field == 'remote_ip'  # Is it related to Ips?
            until_p = field == 'until'  # Is it related to dates?
            from_p = field == 'from'  # Idem.
            next_expr_p = False  # Silly flag to break 2 for cycles
            if field not in user_info and not from_p and not until_p:
                continue
            # For every element in the rule
            for reg_p, expr in expressions_list:
                if group_p:  # Special case: groups
                    if reg_p:  # When it is a regexp
                        # iterate over every group
                        for group in user_info[field]:
                            if expr.match(group):  # if it matches
                                if not_p:  # if must not match
                                    # let's skip to next expr
                                    next_expr_p = True
                                    break
                                else:  # Ok!
                                    return allow_p
                        if next_expr_p:
                            break  # I said: let's skip to next rule ;-)
                    # Simple expression then just check for expr in groups
                    elif expr.lower() in [group.lower()
                                          for group in user_info[field]]:
                        # If expr is in groups then if must not match
                        if not_p:
                            break  # let's skip to next expr
                        else:  # Ok!
                            return allow_p
                elif reg_p:  # Not a group, then easier. If it's a regexp
                    if expr.match(user_info[field]):  # if it matches
                        if not_p:  # If must not match
                            break  # Let's skip to next expr
                        else:
                            return allow_p  # Ok!
                # If it's just a simple expression but an IP!
                elif ip_p and isinstance(expr, tuple):
                    # Then if Ip matches
                    if _ipmatch(user_info['remote_ip'], expr):
                        if not_p:  # If must not match
                            break  # let's skip to next expr
                        else:
                            return allow_p  # ok!
                elif until_p:
                    if time.time() <= expr:
                        if allow_p:
                            break
                        else:
                            return False
                    elif allow_p:
                        return False
                    else:
                        break
                elif from_p:
                    if time.time() >= expr:
                        if allow_p:
                            break
                        else:
                            return False
                    elif allow_p:
                        return False
                    else:
                        break
                # Finally the easiest one!!
                elif expr.lower() == str(user_info[field]).lower():
                    if not_p:  # ...
                        break
                    else:  # ...
                        return allow_p  # ...
            if not_p and not next_expr_p:  # Nothing has matched and we got not
                return allow_p  # Then the whole rule matched!
    except Exception as msg:
        register_exception(alert_admin=True)
        raise InvenioWebAccessFireroleError(msg)
    return default_allow_p  # By default we allow ;-) it'an OpenAccess project
예제 #12
0
    def _handler(req):
        """ This handler is invoked by mod_python with the apache request."""
        allowed_methods = ("GET", "POST", "HEAD", "OPTIONS", "PUT")
        #req.allow_methods(allowed_methods, 1)
        # if req.method not in allowed_methods:
        #    raise apache.SERVER_RETURN, apache.HTTP_METHOD_NOT_ALLOWED

        if req.method == 'OPTIONS':
            # OPTIONS is used to now which method are allowed
            req.headers_out['Allow'] = ', '.join(allowed_methods)
            raise apache.SERVER_RETURN(apache.OK)

        # Set user agent for fckeditor.py, which needs it here
        os.environ["HTTP_USER_AGENT"] = req.headers_in.get('User-Agent', '')

        guest_p = int(current_user.is_guest)

        uri = req.uri
        if uri == '/':
            path = ['']
        else:
            # Let's collapse multiple slashes into a single /
            uri = RE_SLASHES.sub('/', uri)
            path = uri[1:].split('/')

        if CFG_ACCESS_CONTROL_LEVEL_SITE > 1:
            # If the site is under maintainance mode let's return
            # 503 to casual crawler to avoid having the site being
            # indexed
            req.status = 503

        g = _RE_BAD_MSIE.search(req.headers_in.get('User-Agent', "MSIE 6.0"))
        bad_msie = g and float(g.group(1)) < 9.0
        if uri.startswith('/yours') or not guest_p:
            # Private/personalized request should not be cached
            if bad_msie and req.is_https():
                req.headers_out[
                    'Cache-Control'] = 'private, max-age=0, must-revalidate'
            else:
                req.headers_out[
                    'Cache-Control'] = 'private, no-cache, no-store, max-age=0, must-revalidate'
                req.headers_out['Pragma'] = 'no-cache'
                req.headers_out['Vary'] = '*'
        elif not (bad_msie and req.is_https()):
            req.headers_out['Cache-Control'] = 'public, max-age=3600'
            req.headers_out['Vary'] = 'Cookie, ETag, Cache-Control'

        try:
            if req.header_only and not RE_SPECIAL_URI.match(req.uri):
                return root._traverse(req, path, True, guest_p)
            else:
                # bibdocfile have a special treatment for HEAD
                return root._traverse(req, path, False, guest_p)
        except TraversalError:
            raise apache.SERVER_RETURN(apache.HTTP_NOT_FOUND)
        except apache.SERVER_RETURN:
            # This is one of mod_python way of communicating
            raise
        except IOError as exc:
            if 'Write failed, client closed connection' not in "%s" % exc:
                # Workaround for considering as false positive exceptions
                # rised by mod_python when the user close the connection
                # or in some other rare and not well identified cases.
                register_exception(req=req, alert_admin=True)
            raise
        except Exception:
            # send the error message, much more convenient than log hunting
            register_exception(req=req, alert_admin=True)
            raise

        # Serve an error by default.
        raise apache.SERVER_RETURN(apache.HTTP_NOT_FOUND)
예제 #13
0
def forge_email(fromaddr,
                toaddr,
                subject,
                content,
                html_content='',
                html_images=None,
                usebcc=False,
                header=None,
                footer=None,
                html_header=None,
                html_footer=None,
                ln=None,
                charset=None,
                replytoaddr="",
                attachments=None,
                bccaddr=""):
    """Prepare email. Add header and footer if needed.
    @param fromaddr: [string] sender
    @param toaddr: [string or list-of-strings] list of receivers (if string, then
                   receivers are separated by ',')
    @param usebcc: [bool] True for using Bcc in place of To
    @param subject: [string] subject of the email
    @param content: [string] content of the email
    @param html_content: [string] html version of the email
    @param html_images: [dict] dictionary of image id, image path
    @param header: [string] None for the default header
    @param footer: [string] None for the default footer
    @param ln: language
    @charset: [string] the content charset. By default is None which means
    to try to encode the email as ascii, then latin1 then utf-8.
    @param replytoaddr: [string or list-of-strings] to be used for the
                        reply-to header of the email (if string, then
                        receivers are separated by ',')
    @param attachments: list of paths of files to be attached. Alternatively,
        every element of the list could be a tuple: (filename, mimetype)
    @param bccaddr: [string or list-of-strings] to be used for BCC header of the email
                    (if string, then receivers are separated by ',')
    @return: forged email as an EmailMessage object"""
    from invenio_ext.template import render_template_to_string

    ln = default_ln(ln)
    if html_images is None:
        html_images = {}

    content = render_template_to_string(
        'mail_text.tpl',
        content=unicodifier(content),
        header=unicodifier(header),
        footer=unicodifier(footer)).encode('utf8')

    if isinstance(toaddr, list):
        toaddr = ','.join(toaddr)

    if isinstance(bccaddr, list):
        bccaddr = ','.join(bccaddr)

    if isinstance(replytoaddr, list):
        replytoaddr = ','.join(replytoaddr)

    toaddr = remove_temporary_emails(toaddr)

    headers = {}
    kwargs = {'to': [], 'cc': [], 'bcc': []}

    if replytoaddr:
        headers['Reply-To'] = replytoaddr
    if usebcc:
        headers['Bcc'] = bccaddr
        kwargs['bcc'] = toaddr.split(',') + bccaddr.split(',')
        kwargs['to'] = ['Undisclosed.Recipients:']
    else:
        kwargs['to'] = toaddr.split(',')
    headers['From'] = fromaddr
    headers['Date'] = formatdate(localtime=True)
    headers['User-Agent'] = 'Invenio %s at %s' % (cfg['CFG_VERSION'],
                                                  cfg['CFG_SITE_URL'])

    if html_content:
        html_content = render_template_to_string(
            'mail_html.tpl',
            content=unicodifier(html_content),
            header=unicodifier(html_header),
            footer=unicodifier(html_footer)).encode('utf8')

        msg_root = EmailMultiAlternatives(subject=subject,
                                          body=content,
                                          from_email=fromaddr,
                                          headers=headers,
                                          **kwargs)
        msg_root.attach_alternative(html_content, "text/html")

        # if not html_images:
        #    # No image? Attach the HTML to the root
        #    msg_root.attach(msg_text)
        # else:
        if html_images:
            # Image(s)? Attach the HTML and image(s) as children of a
            # "related" block
            msg_related = MIMEMultipart('related')
            # msg_related.attach(msg_text)
            for image_id, image_path in iteritems(html_images):
                attach_embed_image(msg_related, image_id, image_path)
            msg_root.attach(msg_related)
    else:
        msg_root = EmailMessage(subject=subject,
                                body=content,
                                from_email=fromaddr,
                                headers=headers,
                                **kwargs)

    if attachments:
        _mimes = MimeTypes(strict=False)
        for attachment in attachments:
            try:
                mime = None
                if type(attachment) in (list, tuple):
                    attachment, mime = attachment
                if mime is None:
                    # Automatic guessing of mimetype
                    mime = _mimes.guess_type(attachment)[0]
                if mime is None:
                    ext = _mimes.guess_extension(getContentType(attachment))
                    mime = _mimes.guess_type("foo" + ext)[0]
                if not mime:
                    mime = 'application/octet-stream'
                part = MIMEBase(*mime.split('/', 1))
                part.set_payload(open(attachment, 'rb').read())
                Encoders.encode_base64(part)
                part.add_header(
                    'Content-Disposition',
                    'attachment; filename="%s"' % os.path.basename(attachment))
                msg_root.attach(part)
            except:
                from invenio_ext.logging import register_exception
                register_exception(alert_admin=True,
                                   prefix="Can't attach %s" % attachment)

    return msg_root
예제 #14
0
def send_email(
    fromaddr,
    toaddr,
    subject="",
    content="",
    html_content='',
    html_images=None,
    header=None,
    footer=None,
    html_header=None,
    html_footer=None,
    copy_to_admin=0,
    attempt_times=1,
    attempt_sleeptime=10,
    debug_level=0,
    ln=None,
    charset=None,
    replytoaddr="",
    attachments=None,
    bccaddr="",
    forward_failures_to_admin=True,
):
    """Send a forged email to TOADDR from FROMADDR with message created from subjet, content and possibly
    header and footer.
    @param fromaddr: [string] sender
    @param toaddr: [string or list-of-strings] list of receivers (if string, then
                   receivers are separated by ','). BEWARE: If more than once receiptiant is given,
                   the receivers are put in BCC and To will be "Undisclosed.Recipients:".
    @param subject: [string] subject of the email
    @param content: [string] content of the email
    @param html_content: [string] html version of the email
    @param html_images: [dict] dictionary of image id, image path
    @param header: [string] header to add, None for the Default
    @param footer: [string] footer to add, None for the Default
    @param html_header: [string] header to add to the html part, None for the Default
    @param html_footer: [string] footer to add to the html part, None for the Default
    @param copy_to_admin: [int] if 1 add CFG_SITE_ADMIN_EMAIL in receivers
    @param attempt_times: [int] number of tries
    @param attempt_sleeptime: [int] seconds in between tries
    @param debug_level: [int] debug level
    @param ln: [string] invenio language
    @param charset: [string] the content charset. By default is None which means
    to try to encode the email as ascii, then latin1 then utf-8.
    @param replytoaddr: [string or list-of-strings] to be used for the
                        reply-to header of the email (if string, then
                        receivers are separated by ',')
    @param attachments: list of paths of files to be attached. Alternatively,
        every element of the list could be a tuple: (filename, mimetype)
    @param bccaddr: [string or list-of-strings] to be used for BCC header of the email
                    (if string, then receivers are separated by ',')
    @param forward_failures_to_admin: [bool] prevents infinite recursion
                                             in case of admin reporting,
                                             when the problem is not in
                                             the e-mail address format,
                                             but rather in the network

    If sending fails, try to send it ATTEMPT_TIMES, and wait for
    ATTEMPT_SLEEPTIME seconds in between tries.

    e.g.:
    send_email('*****@*****.**', '*****@*****.**', 'Let\'s try!'', 'check 1234', '<strong>check</strong> <em>1234</em><img src="cid:image1">', {'image1': '/tmp/quantum.jpg'})

    @return: [bool]: True if email was sent okay, False if it was not.
    """
    from invenio_ext.logging import register_exception
    ln = default_ln(ln)

    if html_images is None:
        html_images = {}

    if not isinstance(toaddr, list):
        toaddr = toaddr.strip().split(',')
    toaddr = remove_temporary_emails(toaddr)

    # More than one address, let's use Bcc in place of To
    usebcc = len(toaddr) > 1

    if copy_to_admin:
        if cfg['CFG_SITE_ADMIN_EMAIL'] not in toaddr:
            toaddr.append(cfg['CFG_SITE_ADMIN_EMAIL'])

    if not isinstance(bccaddr, list):
        bccaddr = bccaddr.strip().split(',')

    msg = forge_email(fromaddr, toaddr, subject, content, html_content,
                      html_images, usebcc, header, footer, html_header,
                      html_footer, ln, charset, replytoaddr, attachments,
                      bccaddr)

    if attempt_times < 1 or not toaddr:
        try:
            raise EmailError(
                _(
                    'The system is not attempting to send an email from %(x_from)s'
                    ', to %(x_to)s, with body %(x_body)s.',
                    x_from=fromaddr,
                    x_to=toaddr,
                    x_body=content))
        except EmailError:
            register_exception()
        return False
    sent = False
    failure_reason = ''
    while not sent and attempt_times > 0:
        try:
            sent = msg.send()
        except Exception as e:
            failure_reason = str(e)
            register_exception()
            if debug_level > 1:
                try:
                    raise EmailError(
                        _('Error in sending message. \
                        Waiting %(sec)s seconds. Exception is %(exc)s, \
                        while sending email from %(sender)s to %(receipient)s \
                        with body %(email_body)s.',
                          sec=attempt_sleeptime,
                          exc=sys.exc_info()[0],
                          sender=fromaddr,
                          receipient=toaddr,
                          email_body=content))
                except EmailError:
                    register_exception()
        if not sent:
            attempt_times -= 1
            if attempt_times > 0:  # sleep only if we shall retry again
                sleep(attempt_sleeptime)
    if not sent:
        # report failure to the admin with the intended message, its
        # sender and recipients
        if forward_failures_to_admin:
            # prepend '> ' to every line of the original message
            quoted_body = '> ' + '> '.join(content.splitlines(True))

            # define and fill in the report template
            admin_report_subject = _(
                'Error while sending an email: %(x_subject)s',
                x_subject=subject)
            admin_report_body = _(
                "\nError while sending an email.\n"
                "Reason: %(x_reason)s\n"
                "Sender: \"%(x_sender)s\"\n"
                "Recipient(s): \"%(x_recipient)s\"\n\n"
                "The content of the mail was as follows:\n"
                "%(x_body)s",
                x_reason=failure_reason,
                x_sender=fromaddr,
                x_recipient=', '.join(toaddr),
                x_body=quoted_body)

            send_email(cfg['CFG_SITE_ADMIN_EMAIL'],
                       cfg['CFG_SITE_ADMIN_EMAIL'],
                       admin_report_subject,
                       admin_report_body,
                       forward_failures_to_admin=False)

        try:
            raise EmailError(
                _(
                    'Error in sending email from %(x_from)s to %(x_to)s with body'
                    '%(x_body)s.',
                    x_from=fromaddr,
                    x_to=toaddr,
                    x_body=content))
        except EmailError:
            register_exception()
    return sent
예제 #15
0
def send_email(fromaddr,
               toaddr,
               subject="",
               content="",
               html_content='',
               html_images=None,
               header=None,
               footer=None,
               html_header=None,
               html_footer=None,
               copy_to_admin=0,
               attempt_times=1,
               attempt_sleeptime=10,
               debug_level=0,
               ln=None,
               charset=None,
               replytoaddr="",
               attachments=None,
               bccaddr="",
               forward_failures_to_admin=True,
               ):
    """Send a forged email to TOADDR from FROMADDR with message created from subjet, content and possibly
    header and footer.
    @param fromaddr: [string] sender
    @param toaddr: [string or list-of-strings] list of receivers (if string, then
                   receivers are separated by ','). BEWARE: If more than once receiptiant is given,
                   the receivers are put in BCC and To will be "Undisclosed.Recipients:".
    @param subject: [string] subject of the email
    @param content: [string] content of the email
    @param html_content: [string] html version of the email
    @param html_images: [dict] dictionary of image id, image path
    @param header: [string] header to add, None for the Default
    @param footer: [string] footer to add, None for the Default
    @param html_header: [string] header to add to the html part, None for the Default
    @param html_footer: [string] footer to add to the html part, None for the Default
    @param copy_to_admin: [int] if 1 add CFG_SITE_ADMIN_EMAIL in receivers
    @param attempt_times: [int] number of tries
    @param attempt_sleeptime: [int] seconds in between tries
    @param debug_level: [int] debug level
    @param ln: [string] invenio language
    @param charset: [string] the content charset. By default is None which means
    to try to encode the email as ascii, then latin1 then utf-8.
    @param replytoaddr: [string or list-of-strings] to be used for the
                        reply-to header of the email (if string, then
                        receivers are separated by ',')
    @param attachments: list of paths of files to be attached. Alternatively,
        every element of the list could be a tuple: (filename, mimetype)
    @param bccaddr: [string or list-of-strings] to be used for BCC header of the email
                    (if string, then receivers are separated by ',')
    @param forward_failures_to_admin: [bool] prevents infinite recursion
                                             in case of admin reporting,
                                             when the problem is not in
                                             the e-mail address format,
                                             but rather in the network

    If sending fails, try to send it ATTEMPT_TIMES, and wait for
    ATTEMPT_SLEEPTIME seconds in between tries.

    e.g.:
    send_email('*****@*****.**', '*****@*****.**', 'Let\'s try!'', 'check 1234', '<strong>check</strong> <em>1234</em><img src="cid:image1">', {'image1': '/tmp/quantum.jpg'})

    @return: [bool]: True if email was sent okay, False if it was not.
    """
    from invenio_ext.logging import register_exception
    ln = default_ln(ln)

    if html_images is None:
        html_images = {}

    if not isinstance(toaddr, list):
        toaddr = toaddr.strip().split(',')
    toaddr = remove_temporary_emails(toaddr)

    # More than one address, let's use Bcc in place of To
    usebcc = len(toaddr) > 1

    if copy_to_admin:
        if cfg['CFG_SITE_ADMIN_EMAIL'] not in toaddr:
            toaddr.append(cfg['CFG_SITE_ADMIN_EMAIL'])

    if not isinstance(bccaddr, list):
        bccaddr = bccaddr.strip().split(',')

    msg = forge_email(fromaddr, toaddr, subject, content, html_content,
                      html_images, usebcc, header, footer, html_header,
                      html_footer, ln, charset, replytoaddr, attachments,
                      bccaddr)

    if attempt_times < 1 or not toaddr:
        try:
            raise EmailError(_(
                'The system is not attempting to send an email from %(x_from)s'
                ', to %(x_to)s, with body %(x_body)s.', x_from=fromaddr,
                x_to=toaddr, x_body=content))
        except EmailError:
            register_exception()
        return False
    sent = False
    failure_reason = ''
    while not sent and attempt_times > 0:
        try:
            sent = msg.send()
        except Exception as e:
            failure_reason = str(e)
            register_exception()
            if debug_level > 1:
                try:
                    raise EmailError(_('Error in sending message. \
                        Waiting %(sec)s seconds. Exception is %(exc)s, \
                        while sending email from %(sender)s to %(receipient)s \
                        with body %(email_body)s.',
                                       sec=attempt_sleeptime,
                                       exc=sys.exc_info()[0],
                                       sender=fromaddr,
                                       receipient=toaddr,
                                       email_body=content))
                except EmailError:
                    register_exception()
        if not sent:
            attempt_times -= 1
            if attempt_times > 0:  # sleep only if we shall retry again
                sleep(attempt_sleeptime)
    if not sent:
        # report failure to the admin with the intended message, its
        # sender and recipients
        if forward_failures_to_admin:
            # prepend '> ' to every line of the original message
            quoted_body = '> ' + '> '.join(content.splitlines(True))

            # define and fill in the report template
            admin_report_subject = _(
                'Error while sending an email: %(x_subject)s',
                x_subject=subject)
            admin_report_body = _(
                "\nError while sending an email.\n"
                "Reason: %(x_reason)s\n"
                "Sender: \"%(x_sender)s\"\n"
                "Recipient(s): \"%(x_recipient)s\"\n\n"
                "The content of the mail was as follows:\n"
                "%(x_body)s",
                x_reason=failure_reason,
                x_sender=fromaddr,
                x_recipient=', '.join(toaddr),
                x_body=quoted_body)

            send_email(
                cfg['CFG_SITE_ADMIN_EMAIL'],
                cfg['CFG_SITE_ADMIN_EMAIL'],
                admin_report_subject,
                admin_report_body,
                forward_failures_to_admin=False)

        try:
            raise EmailError(_(
                'Error in sending email from %(x_from)s to %(x_to)s with body'
                '%(x_body)s.', x_from=fromaddr, x_to=toaddr, x_body=content))
        except EmailError:
            register_exception()
    return sent
예제 #16
0
def forge_email(fromaddr, toaddr, subject, content, html_content='',
                html_images=None, usebcc=False, header=None, footer=None,
                html_header=None, html_footer=None, ln=None,
                charset=None, replytoaddr="", attachments=None, bccaddr=""):
    """Prepare email. Add header and footer if needed.
    @param fromaddr: [string] sender
    @param toaddr: [string or list-of-strings] list of receivers (if string, then
                   receivers are separated by ',')
    @param usebcc: [bool] True for using Bcc in place of To
    @param subject: [string] subject of the email
    @param content: [string] content of the email
    @param html_content: [string] html version of the email
    @param html_images: [dict] dictionary of image id, image path
    @param header: [string] None for the default header
    @param footer: [string] None for the default footer
    @param ln: language
    @charset: [string] the content charset. By default is None which means
    to try to encode the email as ascii, then latin1 then utf-8.
    @param replytoaddr: [string or list-of-strings] to be used for the
                        reply-to header of the email (if string, then
                        receivers are separated by ',')
    @param attachments: list of paths of files to be attached. Alternatively,
        every element of the list could be a tuple: (filename, mimetype)
    @param bccaddr: [string or list-of-strings] to be used for BCC header of the email
                    (if string, then receivers are separated by ',')
    @return: forged email as an EmailMessage object"""
    from invenio_ext.template import render_template_to_string

    ln = default_ln(ln)
    if html_images is None:
        html_images = {}

    content = render_template_to_string('mail_text.tpl',
                                        content=unicodifier(content),
                                        header=unicodifier(header),
                                        footer=unicodifier(footer)
                                        ).encode('utf8')

    if isinstance(toaddr, list):
        toaddr = ','.join(toaddr)

    if isinstance(bccaddr, list):
        bccaddr = ','.join(bccaddr)

    if isinstance(replytoaddr, list):
        replytoaddr = ','.join(replytoaddr)

    toaddr = remove_temporary_emails(toaddr)

    headers = {}
    kwargs = {'to': [], 'cc': [], 'bcc': []}

    if replytoaddr:
        headers['Reply-To'] = replytoaddr
    if usebcc:
        headers['Bcc'] = bccaddr
        kwargs['bcc'] = toaddr.split(',') + bccaddr.split(',')
        kwargs['to'] = ['Undisclosed.Recipients:']
    else:
        kwargs['to'] = toaddr.split(',')
    headers['From'] = fromaddr
    headers['Date'] = formatdate(localtime=True)
    headers['User-Agent'] = 'Invenio %s at %s' % (cfg['CFG_VERSION'],
                                                  cfg['CFG_SITE_URL'])

    if html_content:
        html_content = render_template_to_string(
            'mail_html.tpl',
            content=unicodifier(html_content),
            header=unicodifier(html_header),
            footer=unicodifier(html_footer)
        ).encode('utf8')

        msg_root = EmailMultiAlternatives(subject=subject, body=content,
                                          from_email=fromaddr,
                                          headers=headers, **kwargs)
        msg_root.attach_alternative(html_content, "text/html")

        # if not html_images:
        #    # No image? Attach the HTML to the root
        #    msg_root.attach(msg_text)
        # else:
        if html_images:
            # Image(s)? Attach the HTML and image(s) as children of a
            # "related" block
            msg_related = MIMEMultipart('related')
            # msg_related.attach(msg_text)
            for image_id, image_path in iteritems(html_images):
                attach_embed_image(msg_related, image_id, image_path)
            msg_root.attach(msg_related)
    else:
        msg_root = EmailMessage(subject=subject, body=content,
                                from_email=fromaddr, headers=headers, **kwargs)

    if attachments:
        _mimes = MimeTypes(strict=False)
        for attachment in attachments:
            try:
                mime = None
                if type(attachment) in (list, tuple):
                    attachment, mime = attachment
                if mime is None:
                    # Automatic guessing of mimetype
                    mime = _mimes.guess_type(attachment)[0]
                if mime is None:
                    ext = _mimes.guess_extension(getContentType(attachment))
                    mime = _mimes.guess_type("foo" + ext)[0]
                if not mime:
                    mime = 'application/octet-stream'
                part = MIMEBase(*mime.split('/', 1))
                part.set_payload(open(attachment, 'rb').read())
                Encoders.encode_base64(part)
                part.add_header(
                    'Content-Disposition',
                    'attachment; filename="%s"' %
                    os.path.basename(attachment))
                msg_root.attach(part)
            except:
                from invenio_ext.logging import register_exception
                register_exception(
                    alert_admin=True,
                    prefix="Can't attach %s" %
                    attachment)

    return msg_root
예제 #17
0
def main():
    """Main function that analyzes command line input and calls whatever
    is appropriate. """

    from invenio_access.firerole import repair_role_definitions
    from invenio_access.control import (acc_add_default_settings,
                                        acc_reset_default_settings)
    from invenio_base.globals import cfg

    DEF_DEMO_USER_ROLES = cfg.get('DEF_DEMO_USER_ROLES', tuple())
    DEF_DEMO_ROLES = cfg.get('DEF_DEMO_ROLES', tuple())
    DEF_DEMO_AUTHS = cfg.get('DEF_DEMO_AUTHS', tuple())

    ## parse command line:
    # set user-defined options:
    options = {'user': '', 'reset': 0, 'compile': 0, 'add': 0, 'demo': 0}
    try:
        opts, args = getopt.getopt(
            sys.argv[1:], "hVu:racD",
            ["help", "version", "user="******"reset", "add", "compile", "demo"])
    except getopt.GetoptError as err:
        usage(1, err)
    try:
        for opt in opts:
            if opt[0] in ("-h", "--help"):
                usage(0)
            elif opt[0] in ("-V", "--version"):
                print(__revision__)
                sys.exit(0)
            elif opt[0] in ("-u", "--user"):
                options["user"] = opt[1]
            elif opt[0] in ("-r", "--reset"):
                options["reset"] = 1
            elif opt[0] in ("-a", "--add"):
                options["add"] = 1
            elif opt[0] in ("-c", "--compile"):
                options["compile"] = 1
            elif opt[0] in ("-D", "--demo"):
                options["demo"] = 1
            else:
                usage(1)
        if options['add'] or options['reset'] or options['compile']:
            #if acca.acc_get_action_id('cfgwebaccess'):
            #    # Action exists hence authentication works :-)
            #    options['user'] = authenticate(options['user'],
            #        authorization_msg="WebAccess Administration",
            #        authorization_action="cfgwebaccess")
            if options['reset'] and options['demo']:
                acc_reset_default_settings([cfg['CFG_SITE_ADMIN_EMAIL']],
                                           DEF_DEMO_USER_ROLES, DEF_DEMO_ROLES,
                                           DEF_DEMO_AUTHS)
                print("Reset default demo site settings.")
            elif options['reset']:
                acc_reset_default_settings([cfg['CFG_SITE_ADMIN_EMAIL']])
                print("Reset default settings.")
            elif options['add'] and options['demo']:
                acc_add_default_settings([cfg['CFG_SITE_ADMIN_EMAIL']],
                                         DEF_DEMO_USER_ROLES, DEF_DEMO_ROLES,
                                         DEF_DEMO_AUTHS)
                print("Added default demo site settings.")
            elif options['add']:
                acc_add_default_settings([cfg['CFG_SITE_ADMIN_EMAIL']])
                print("Added default settings.")
            if options['compile']:
                repair_role_definitions()
                print("Compiled firewall like role definitions.")
        else:
            usage(1, "You must specify at least one command")
    except StandardError as e:
        from invenio_ext.logging import register_exception
        register_exception()
        usage(e)
    return