コード例 #1
0
 def email_new_user_summary(self, frequency_of_timed_task="days=1"):
     """
     query for all users in last <timedelta> and email 
     """
     frequency_of_timed_task = timedelta_from_str(frequency_of_timed_task)
     
     from civicboom.model import Member
     members = Session.query(Member) \
                 .with_polymorphic('*') \
                 .filter(Member.join_date>=normalize_datetime(now()) - frequency_of_timed_task) \
                 .all()
     
     if not members:
         log.debug('Report not generated: no new members in %s' % frequency_of_timed_task)
         return response_completed_ok
     
     from civicboom.lib.communication.email_lib import send_email
     send_email(
         config['email.event_alert'],
         subject      ='new user registration summary',
         content_html = render(
                         '/email/admin/summary_new_users.mako',
                         extra_vars = {
                             "members"   : members                 ,
                             "timedelta" : frequency_of_timed_task ,
                         }
                     ),
     )
     
     return response_completed_ok
コード例 #2
0
ファイル: accounts.py プロジェクト: civicboom/civicboom
def send_verifiy_email(user, controller='account', action='verify_email', message=None, subject=None):
    if not subject:
        subject = _('verify e-mail address')
    if not message:
        message = _('verify this email address')
#    Session.refresh(user)
    validation_link  = validation_url(user, controller, action)
    message          = _('Please %s by clicking on, or copying the following link into your browser: %s') % (message, validation_link)
    if action == 'verify_email':
        send_email(user.email_unverified, subject=subject, content_text=message)
    else:
        user.send_email(subject=subject, content_text=message)
コード例 #3
0
ファイル: misc.py プロジェクト: civicboom/civicboom
    def contact_us(self, **kwargs):
        if not request.POST:
            return action_ok(
            )  # Render the contact form by autolocating the template
        else:
            user_log.info("Sending contact email")

            content_text = "Contact Form\r\n\r\n"
            for key, value in kwargs.iteritems():
                content_text += "%s: %s\r\n" % (key, value)

            send_email(config['email.contact'],
                       subject=_('_site_name contact_form'),
                       content_text=content_text,
                       reply_to=kwargs.get('email', ''))
            return action_ok(
                _("Thank you for your interest, we will contact you shortly"),
                code=201)
コード例 #4
0
ファイル: misc.py プロジェクト: civicboom/civicboom
    def upgrade_request(self, **kwargs):
        if not request.POST:
            return
        schema = DynamicSchema()
        schema.chained_validators = []
        schema.fields['name'] = UnicodeString(not_empty=True)
        schema.fields['phone'] = UnicodeString(not_empty=True)
        schema.fields['email'] = Email(not_empty=True)
        if not c.logged_in_user:
            schema.fields['recaptcha_challenge_field'] = UnicodeString(
                not_empty=True)
            schema.fields['recaptcha_response_field'] = UnicodeString(
                not_empty=True)
            schema.chained_validators.append(
                ReCaptchaValidator(request.environ['REMOTE_ADDR']))

        data = {'upgrade_request': kwargs}
        data = validate_dict(data,
                             schema,
                             dict_to_validate_key='upgrade_request')

        from civicboom.lib.communication.email_lib import send_email
        form_string = ''
        for key, value in kwargs.iteritems():
            form_string += '\n%s: %s' % (key, value)

        if c.logged_in_user:
            form_string += '\nlogged_in_user: %s' % (c.logged_in_user.username)
            form_string += '\nlogged_in_persona: %s' % (
                c.logged_in_persona.username)
        else:
            form_string += '\nUser not logged in!'

        send_email(config['email.contact'],
                   subject='Civicboom',
                   content_text='upgrade account request: %s' % form_string)

        return action_ok(_('upgrade request sent'))
コード例 #5
0
ファイル: misc.py プロジェクト: civicboom/civicboom
            def submit_feedback(**kwargs):
                if c.logged_in_user:
                    kwargs['from'] = request.environ['logged_in_user_email']
                else:
                    if kwargs.get('simple_captcha') != 'xyz':
                        raise action_error('invalid capture')

                if not kwargs.get('env'):
                    kwargs['env'] = ''
                    for key, value in request.environ.iteritems():
                        kwargs['env'] += "%s:%s\n" % (key, value)
                if kwargs.get('referer'):
                    kwargs['referer'] = unquote_plus(kwargs['referer'])
                content_text = "%(referer)s\n\n%(category)s\n\n%(from_)s\n\n%(message)s\n\n%(env)s" % dict(
                    message=kwargs.get('message'),
                    env=unquote_plus(kwargs.get('env')),
                    from_=kwargs.get('from'),
                    category=kwargs.get('category'),
                    referer=kwargs.get('referer'))
                send_email(config['email.contact'],
                           subject=_('_site_name feedback'),
                           content_text=content_text,
                           reply_to=kwargs['from'])
                return action_ok(_("Thank you for your feedback"), code=201)
コード例 #6
0
 def send_email(self, **kargs):
     from civicboom.lib.communication.email_lib import send_email
     send_email(self, **kargs)
コード例 #7
0
def send_notification(members, message):  #members, rendered_message
    """
    Threaded message system
    Save and handles propogating the message to different technologies for all members of a group or an indvidual
    """

    #log.debug('Running send_notification to members=%s message=%s' % (members,message))

    message['source'] = get_member(
        message.get('source') or message.get('source_id')) or message.get(
            'source')  # Attempt to normalize source member

    # Multiple memebrs
    if isinstance(members, list):

        for member in get_members(members, expand_group_members=True):
            message[
                'target_username'] = member.id  # Overlay the direct target member of this message as an additional param
            send_notification(member, message)
            #if member.__type__ == 'group':
            #    send_notification(get_group_member_username_list(member), **kwargs)
        Session.commit(
        )  # No need to commits as all workers commit at end by default

    # Single member
    else:
        member = get_member(members)

        # AllanC - Messages can be passed without a default_route or name if they are not auto generated notifications
        #          in this case they are deemed "user to user" messages and have enforced default template and route
        if 'default_route' not in message:
            message['default_route'] = 'e'
        if 'name' not in message:
            message['name'] = 'message'

        # Get propergate settings - what other technologies is this message going to be sent over
        # Attempt to get routing settings from the member's config; if that fails, use the
        # message's default routing
        message_tech_options = member.config.get(
            "route_" + message.get('name', 'default'),
            message.get('default_route'))

        # Iterate over each letter of tech_options - each letter is a code for the technology to send it to
        # e.g 'c'  will send to Comufy
        #     'et' will send to email and twitter
        #     'n'  is a normal notification
        #     ''   will dispose of the message because it has nowhere to go
        for route in message_tech_options:

            # -- Comufy --------------------------------------------------------
            # very unused, untested, commented out for coverage
            #if route == 'c':
            #    pass

            # -- Email ---------------------------------------------------------
            if route == 'e':
                if member.__type__ == 'user':  # Only send emails to individual users

                    # Feature #498 - Check for existing email template and attempt to render
                    def notification_template(template):
                        template_path = os.path.join("email", "notifications",
                                                     template + ".mako")
                        #if os.path.exists(os.path.join(config['path.templates'], template_path)):
                        if os.path.exists(
                                os.path.join("civicboom/templates",
                                             template_path)):
                            return template_path
                        return 'email/notifications/default.mako'

                    #if config['debug'] == True or config['debug'] == "true": # debug is a string, so config['debug'] == "false" == Trues
                    if config['worker.queue.type'] == 'inline':
                        c = render_mako(notification_template(
                            message.get('name')),
                                        extra_vars={
                                            "kwargs": message,
                                        })
                    else:  # pragma: no cover - test mode uses inline rendering, this is stand-alone
                        l = TemplateLookup(
                            directories=['.', 'civicboom/templates'],
                            input_encoding='utf-8',
                            output_encoding='utf-8')
                        f = os.path.join(
                            "civicboom/templates",
                            notification_template(message.get('name')))
                        t = Template(filename=f, lookup=l)
                        c = t.render_unicode(kwargs=message, h=helpers)
                    send_email(
                        member,
                        subject=message.get(
                            'subject'),  #, _('_site_name notification')
                        content_html=c,
                    )

            # -- Notification --------------------------------------------------
            # Save message in message table (to be seen as a notification)
            if route == 'n':
                m = Message()
                m.subject = message['subject']
                m.content = message['content']
                m.target = member
                Session.add(m)
                #member.messages_to.append(m)
                #invalidate_list_version('mesages_index', 'notification', m.target.id) # AllanC - we can replace this invalidation with a sqlalchemy list watching trigger maybe?

            # ------------------------------------------------------------------

        log.debug("%s was sent the message '%s', routing via %s" %
                  (member.username, message.get('name'), message_tech_options))

    return True
コード例 #8
0
ファイル: register.py プロジェクト: civicboom/civicboom
    def new_user(self, id=None, **kwargs):
        """
        Register new user - look at exisiting user record and identify additioinal required fields to complete upload
        """
        registration_template = "/html/%s/account/register.mako" % (
            "mobile" if c.subformat == "mobile" else "web")
        # registration_template = "/html/web/account/register.mako"

        c.new_user = _get_member(id)

        # Validate User
        if c.logged_in_persona and c.logged_in_persona == c.new_user:  # from janrain login
            pass
        elif verify_email_hash(c.new_user,
                               kwargs.get('hash')):  # or from email hash
            c.logged_in_user = c.new_user  #fake logged in user for rendering template
            c.logged_in_persona = c.new_user
        else:
            raise action_error(
                code=403,
                message=
                "Unable to verify email hash - it may already have been validated?"
            )

        # Build required fields list from current user data - the template will then display these and a custom validator will be created for them
        c.required_fields = ['username', 'email', 'password', 'name', 'dob']
        if not c.logged_in_persona.id.startswith(new_user_prefix):
            c.required_fields.remove('username')
        if c.logged_in_persona.email or c.logged_in_persona.email_unverified:
            c.required_fields.remove('email')
        if len(c.logged_in_persona.login_details) > 0:
            c.required_fields.remove('password')
        if c.logged_in_persona.config["dob"] != u"":
            c.required_fields.remove('dob')

        # If no post data, display the registration form with required fields
        if request.environ['REQUEST_METHOD'] == 'GET':
            return render(registration_template)

        # Build a dynamic validation scema based on these required fields and validate the form
        schema = build_schema(*c.required_fields)
        schema.fields['terms'] = validators.NotEmpty(messages={
            'missing':
            'You must agree to the terms and conditions'
        })  # In addtion to required fields add the terms checkbox validator
        schema.fields['name'] = validators.NotEmpty(
            messages={
                'missing':
                'Please give us your full name as you wish it to appear on your profile'
            })
        schema.fields['help_type'] = formencode.validators.OneOf(
            ['org', 'ind'],
            messages={'missing':
                      'Please select a help type'})  #, if_missing='ind'
        # schema.fields['help_type'] = validators.NotEmpty(messages={'missing': 'Please select a user type'})
        data = {'register': kwargs}
        data = validate_dict(data,
                             schema,
                             dict_to_validate_key='register',
                             template_error='account/register')
        form = data['register']

        #try: # Form validation
        #    form = schema.to_python(kwargs) #dict(request.params)
        #except formencode.Invalid as error:  # If the form has errors overlay those errors over the previously rendered form
        #    form_result = error.value
        #    form_errors = error.error_dict or {}
        # htmlfill does not work with HTML5 ... bugger
        # return formencode.htmlfill.render(render(registration_template) , defaults = form_result , errors = form_errors, prefix_error=False)

        # If the validator has not forced a page render
        # then the data is fine - save the new user data
        if 'username' in form:
            c.logged_in_persona.id = form['username']
        if 'name' in form:
            c.logged_in_persona.name = form['name']
        if 'dob' in form:
            c.logged_in_persona.config['dob'] = str(form['dob'])
        if 'email' in form:
            c.logged_in_persona.email_unverified = form['email']
        if 'password' in form:
            set_password(c.logged_in_persona,
                         form['password'],
                         delay_commit=True)
        c.logged_in_persona.status = "active"
        if form['help_type'] == 'org':
            c.logged_in_persona.extra_fields['help_type'] = form['help_type']

        # AllanC - in offline demo mode ensure every user has the maximum user rights
        if config['demo_mode']:
            c.logged_in_persona.account_type = 'corp_plus'

        Session.add(
            c.logged_in_persona)  #AllanC - is this needed? Already in session?
        Session.commit()

        if c.logged_in_persona.email_unverified:
            send_verifiy_email(c.logged_in_persona)
            set_flash_message(
                _('Please check your email to validate your email address'))

        c.logged_in_persona.send_email(
            subject=_('Welcome to _site_name'),
            content_html=render(
                '/email/welcome.mako',
                extra_vars={'registered_user': c.logged_in_persona}))

        # Follow pending users from extra_fields
        for member in [
                _get_member(username)
                for username in c.logged_in_persona.extra_fields.pop(
                    'on_register_follow', '').split(',')
        ]:
            if member:
                c.logged_in_persona.follow(member, delay_commit=True)
        for member in [
                _get_member(username)
                for username in c.logged_in_persona.extra_fields.pop(
                    'on_register_follow_mutual', '').split(',')
        ]:
            if member and member.config['allow_registration_follows']:
                member.follow(c.logged_in_persona, delay_commit=True)
        Session.commit()

        # AllanC - Temp email alert for new user
        send_email(config['email.event_alert'],
                   subject='new signup',
                   content_text='%s - %s - %s - %s' %
                   (c.logged_in_persona.id, c.logged_in_persona.name,
                    c.logged_in_persona.email_normalized, form['help_type']))

        user_log.info("Registered new user")
        set_flash_message(
            _("Congratulations, you have successfully signed up to _site_name."
              ))
        # GregM: prompt_aggregate on new user :D
        ##signin_user_and_redirect(c.logged_in_persona, 'registration', prompt_aggregate=True)
        # Proto: only want to show profile introduction page if the user is registering using the desktop website
        redirection_uri = url(
            controller='misc',
            action='how_to') if c.subformat == "web" else url(
                controller='profile', action='index')
        signin_user_and_redirect(c.logged_in_persona,
                                 'registration',
                                 redirect_url=redirection_uri)
コード例 #9
0
    def create(self, **kwargs):
        """
        POST /groups: Create a new group

        Creates a new group with the specified username with the currently
        logged in user as as administrator of the new group

        @api groups 1.0 (WIP)
        
        @param username                   a unique username, cannot clash with existing usernames
        @param name                       display name
        @param description                description of groups purpose
        @param default_role
            admin
            editor
            contributor
            observer
        @param join_mode
            public
            invite
            invite_and_request
        @param member_visibility
            public
            private 
        @param default_content_visibility (plus account required)
            public
            private 
        
        @return 400  data invalid (ie, username that already exisits)
        @return 201  group created, data.id = new group id
        @return 301  if format redirect specifyed will redirect to show group
        """

        create_push_assignment = kwargs.get('create_push_assignment')
        if create_push_assignment:
            del kwargs['create_push_assignment']

        # url('groups') + POST
        # if only display name is specified, generate a user name
        if not kwargs.get('username') and kwargs.get("name"):
            kwargs["username"] = _gen_username(
                make_username(kwargs.get("name")))

        # if only user name is specified, generate a display name
        if not kwargs.get('name') and kwargs.get("username"):
            kwargs["name"] = kwargs.get("username")

        if not c.logged_in_persona.has_account_required('plus'):
            if not kwargs.get('member_visibility'):
                kwargs['member_visibility'] = 'public'
            if not kwargs.get('default_content_visibility'):
                kwargs['default_content_visibility'] = 'public'

        # Need to validate before creating group, not sure how we could do this via settings controller :S GregM
        data = {'settings': kwargs, 'action': 'create'}
        data = validate_dict(data,
                             CreateGroupSchema(),
                             dict_to_validate_key='settings',
                             template_error='groups/edit')
        group_dict = data['settings']

        # Create and set group admin here!
        group = Group()
        group.id = group_dict['username']
        group.name = group_dict['name']
        group.status = 'active'
        group_admin = GroupMembership()
        group_admin.member = c.logged_in_persona
        group_admin.role = "admin"
        group.members_roles.append(group_admin)
        group.payment_account = c.logged_in_persona.payment_account  # The group is allocated the same payment account as the creator. All groups are free but if they want the plus features like approval and private content then this is needed

        # GregM: Dirty hack, again... In demo mode users & groups don't have payment accounts, we need to override the account_type manually
        if config['demo_mode']:
            group.account_type = c.logged_in_persona.account_type

        #AllanC - TODO - limit number of groups a payment account can support - the could be the differnece between plus and corporate

        # GregM: Create current user as admin of group too to allow them to admin group (until permission tree is sorted!)
        #if isinstance(c.logged_in_persona, Group):
        #    group_admin_user        = GroupMembership()
        #    group_admin_user.member = c.logged_in_user
        #    group_admin_user.role   = "admin"
        #    group.members_roles.append(group_admin_user)

        Session.add(group)
        Session.commit()

        # AllanC - Hack
        # The group has been created, but the additional feilds handled by the settings controller need to be updated (e.g. description and logo image)
        # However, we have not set c.logged_in_persona so the call to the settings controller will not have the permissions for the newly created group
        # We fake the login here
        # We cant use set_persona as this called the set_persona controller action and calls a redirect
        logged_in_persona = c.logged_in_persona  # have to remeber previous persona to return to or set_persona below thinks were already swiched and will perform no action
        logged_in_persona_role = c.logged_in_persona_role
        c.logged_in_persona = group
        c.logged_in_persona_role = 'admin'

        # AllanC - old call? to be removed?
        # self.update(group.username, **kwargs) # Overlay any additional form fields over the new group object using the update method - also intercepts if format is redirect

        # Call settings controller to update group settings!
        kwargs['panel'] = 'general'

        settings_update(group, private=True, **kwargs)

        # GregM: Create new request for group (Arrgh, have to fudge the format otherwise we cause a redirect):
        format = c.format
        if create_push_assignment:
            c.format = 'python'
            assignment = create_content(
                type='assignment',
                private=False,
                title=_("Send us your stories"),
                content=
                _("Join us in making the news by telling us your stories, sending in videos, pictures or audio: Get recognition and get published - share your news with us now!"
                  ),
                format="python")
            group.config['push_assignment'] = assignment.get('data',
                                                             {}).get('id')

        c.format = format

        c.logged_in_persona = logged_in_persona
        c.logged_in_persona_role = logged_in_persona_role

        user_log.info("Created Group #%s (%s)" % (group.id, group.name))

        # AllanC - Temp email alert for new group
        send_email(config['email.event_alert'],
                   subject='new group',
                   content_text='%s - %s by %s' %
                   (c.logged_in_persona.username, c.logged_in_persona.name,
                    c.logged_in_user.username))

        # GregM: prompt_aggregate for new group :)
        set_persona(
            group,
            prompt_aggregate=True)  # Will redirect if in html or redirect mode

        return action_ok(message=_('group created'),
                         data={'id': group.id},
                         code=201)
コード例 #10
0
ファイル: actions.py プロジェクト: civicboom/civicboom
def flag(obj,
         raising_member=None,
         type="automated",
         comment=None,
         url_base=None,
         delay_commit=False,
         moderator_address=None):
    """
    if url_base is included an alternate URL generator to avert the use of the pylons one
    """
    flag = FlaggedEntity()
    flag.raising_member = get_member(raising_member)

    if isinstance(obj, Content):
        flag.offending_content = obj
    if isinstance(obj, Member):
        flag.offending_member = obj
    if isinstance(obj, Message):
        flag.offending_message = obj

    flag.comment = strip_html_tags(comment)
    flag.type = type
    Session.add(flag)
    if not delay_commit:
        Session.commit()
    else:
        Session.flush()

    # Send email to alert moderator
    raising_member_username = '******'
    try:
        raising_member_username = flag.raising_member.id
    except:
        pass

    # Base email text
    email_text_dict = {
        "raising_member": raising_member_username,
        "type": type,
        "comment": flag.comment,
        "action_ignore": '',
        "action_delete": '',
    }
    email_text = """
--- Report ---

Reporter: %(raising_member)s
Category: %(type)s

%(comment)s

--- Actions ---

If the content is ok, click here to remove the flag:
  %(action_ignore)s

If the content is not ok, click here to hide it from the site:
  %(action_delete)s

"""

    # Additional Content text
    if flag.offending_content:
        email_text_dict.update({
            "creator_name":
            flag.offending_content.creator.id,
            "creator_url":
            url('member',
                id=flag.offending_content.creator.id,
                qualified=True,
                sub_domain="www"),
            "content_url":
            url('content',
                id=flag.offending_content.id,
                qualified=True,
                sub_domain="www"),
            "content_title":
            flag.offending_content.title,
            "content_body":
            flag.offending_content.content,
            "action_ignore":
            url("admin/moderate?kay=yay&content_id=%s" %
                flag.offending_content.id,
                qualified=True),  #sub_domain="www"),
            "action_delete":
            url("admin/moderate?kay=nay&content_id=%s" %
                flag.offending_content.id,
                qualified=True),  #sub_domain="www"),
        })
        email_text = email_text + """
--- Reported Content ---

Title:  %(content_title)s
        %(content_url)s
Author: %(creator_name)s
        %(creator_url)s

%(content_body)s
"""

    if flag.offending_member:
        log.error('member flaging not implemented yet')

    if flag.offending_message:
        log.error('message flaging not implemented yet')

    email_text = email_text % email_text_dict
    send_email(
        moderator_address,
        subject='flagged content [%s]' % type,
        content_text=email_text,
        content_html="<pre>" + email_text + "</pre>",
    )
コード例 #11
0
 def send_admin_email(extra_error):
     send_email(config['email.payment_alert'],
         subject='Regrade Fail',
         content_text='Oops, something went wrong when %s (account %s) tried to regrade. %s' % (c.logged_in_persona.id, account.id, extra_error),
     )
コード例 #12
0
 def send_email_admins(account, **kwargs):
     for user in account.get_admins():
         send_email(user, **kwargs)
コード例 #13
0
def send_payment_admin_email(subject, content_text):
    send_email(config['email.payment_alert'],
        subject=subject,
        content_text=content_text,
    )