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
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)
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)
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'))
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)
def send_email(self, **kargs): from civicboom.lib.communication.email_lib import send_email send_email(self, **kargs)
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
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)
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)
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>", )
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), )
def send_email_admins(account, **kwargs): for user in account.get_admins(): send_email(user, **kwargs)
def send_payment_admin_email(subject, content_text): send_email(config['email.payment_alert'], subject=subject, content_text=content_text, )