def sendmail(fromaddr, destinations, text, reply_to, subject, message_id, in_reply_to=None, sender=None, references=None): from allura import model as M addrs_plain = [] addrs_html = [] addrs_multi = [] if fromaddr is None: fromaddr = g.noreply elif '@' not in fromaddr: log.warning('Looking up user with fromaddr: %s', fromaddr) user = M.User.query.get(_id=ObjectId(fromaddr), disabled=False) if not user: log.warning('Cannot find user with ID: %s', fromaddr) fromaddr = g.noreply else: fromaddr = user.email_address_header() # Divide addresses based on preferred email formats for addr in destinations: if mail_util.isvalid(addr): addrs_plain.append(addr) else: try: user = M.User.query.get(_id=ObjectId(addr), disabled=False) if not user: log.warning('Cannot find user with ID: %s', addr) continue except: log.exception('Error looking up user with ID: %r' % addr) continue addr = user.email_address_header() if not addr and user.email_addresses: addr = user.email_addresses[0] log.warning( 'User %s has not set primary email address, using %s', user._id, addr) if not addr: log.error( "User %s (%s) has not set any email address, can't deliver", user._id, user.username) continue if user.get_pref('email_format') == 'plain': addrs_plain.append(addr) elif user.get_pref('email_format') == 'html': addrs_html.append(addr) else: addrs_multi.append(addr) htmlparser = HTMLParser.HTMLParser() plain_msg = mail_util.encode_email_part(htmlparser.unescape(text), 'plain') html_text = g.forge_markdown(email=True).convert(text) html_msg = mail_util.encode_email_part(html_text, 'html') multi_msg = mail_util.make_multipart_message(plain_msg, html_msg) smtp_client.sendmail( addrs_multi, fromaddr, reply_to, subject, message_id, in_reply_to, multi_msg, sender=sender, references=references) smtp_client.sendmail( addrs_plain, fromaddr, reply_to, subject, message_id, in_reply_to, plain_msg, sender=sender, references=references) smtp_client.sendmail( addrs_html, fromaddr, reply_to, subject, message_id, in_reply_to, html_msg, sender=sender, references=references)
def sendmail(fromaddr, destinations, text, reply_to, subject, message_id, in_reply_to=None, sender=None, references=None, metalink=None): ''' Send an email to the specified list of destinations with respect to the preferred email format specified by user. It is best for broadcast messages. :param fromaddr: ObjectId or str(ObjectId) of user, or email address str ''' from allura import model as M addrs_plain = [] addrs_multi = [] if fromaddr is None: fromaddr = g.noreply elif not isinstance(fromaddr, basestring) or '@' not in fromaddr: log.warning('Looking up user with fromaddr: %s', fromaddr) user = M.User.query.get(_id=ObjectId(fromaddr), disabled=False, pending=False) if not user: log.warning('Cannot find user with ID: %s', fromaddr) fromaddr = g.noreply else: fromaddr = user.email_address_header() # Divide addresses based on preferred email formats for addr in destinations: if mail_util.isvalid(addr): addrs_plain.append(addr) else: try: user = M.User.query.get(_id=ObjectId(addr), disabled=False, pending=False) if not user: log.warning('Cannot find user with ID: %s', addr) continue except: log.exception('Error looking up user with ID: %r' % addr) continue addr = user.email_address_header() if not addr and user.email_addresses: addr = user.email_addresses[0] log.warning( 'User %s has not set primary email address, using %s', user._id, addr) if not addr: log.error( "User %s (%s) has not set any email address, can't deliver", user._id, user.username) continue if user.get_pref('email_format') == 'plain': addrs_plain.append(addr) else: addrs_multi.append(addr) multi_msg, plain_msg = create_multipart_msg(text, metalink) smtp_client.sendmail( addrs_multi, fromaddr, reply_to, subject, message_id, in_reply_to, multi_msg, sender=sender, references=references) smtp_client.sendmail( addrs_plain, fromaddr, reply_to, subject, message_id, in_reply_to, plain_msg, sender=sender, references=references)
def sendmail(fromaddr, destinations, text, reply_to, subject, message_id, in_reply_to=None, sender=None): from allura import model as M addrs_plain = [] addrs_html = [] addrs_multi = [] if fromaddr is None: fromaddr = u'*****@*****.**' elif '@' not in fromaddr: log.warning('Looking up user with fromaddr: %s', fromaddr) user = M.User.query.get(_id=ObjectId(fromaddr), disabled=False) if not user: log.warning('Cannot find user with ID: %s', fromaddr) fromaddr = u'*****@*****.**' else: fromaddr = user.email_address_header() # Divide addresses based on preferred email formats for addr in destinations: if mail_util.isvalid(addr): addrs_plain.append(addr) else: try: user = M.User.query.get(_id=ObjectId(addr), disabled=False) if not user: log.warning('Cannot find user with ID: %s', addr) continue except: log.exception('Error looking up user with ID: %r' % addr) continue addr = user.email_address_header() if not addr and user.email_addresses: addr = user.email_addresses[0] log.warning('User %s has not set primary email address, using %s', user._id, addr) if not addr: log.error("User %s (%s) has not set any email address, can't deliver", user._id, user.username) continue if user.get_pref('email_format') == 'plain': addrs_plain.append(addr) elif user.get_pref('email_format') == 'html': addrs_html.append(addr) else: addrs_multi.append(addr) htmlparser = HTMLParser.HTMLParser() plain_msg = mail_util.encode_email_part(htmlparser.unescape(text), 'plain') html_text = g.forge_markdown(email=True).convert(text) html_msg = mail_util.encode_email_part(html_text, 'html') multi_msg = mail_util.make_multipart_message(plain_msg, html_msg) smtp_client.sendmail( addrs_multi, fromaddr, reply_to, subject, message_id, in_reply_to, multi_msg, sender=sender) smtp_client.sendmail( addrs_plain, fromaddr, reply_to, subject, message_id, in_reply_to, plain_msg, sender=sender) smtp_client.sendmail( addrs_html, fromaddr, reply_to, subject, message_id, in_reply_to, html_msg, sender=sender)
def _update_emails(self, user, admin=False, form_params={}): # not using **kw in method signature, to ensure 'admin' can't be passed in via a form submit kw = form_params addr = kw.pop('addr', None) new_addr = kw.pop('new_addr', None) primary_addr = kw.pop('primary_addr', None) provider = plugin.AuthenticationProvider.get(request) for i, (old_a, data) in enumerate(zip(user.email_addresses, addr or [])): obj = user.address_object(old_a) if data.get('delete') or not obj: if not admin and (not kw.get('password') or not provider.validate_password( user, kw.get('password'))): flash( 'You must provide your current password to delete an email', 'error') return if primary_addr == user.email_addresses[i]: if select_new_primary_addr(user, ignore_emails=primary_addr) is None \ and asbool(config.get('auth.require_email_addr', False)): flash( 'You must have at least one verified email address.', 'error') return else: # clear it now, a new one will get set below user.set_pref('email_address', None) primary_addr = None user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='') h.auditlog_user('Email address deleted: %s', user.email_addresses[i], user=user) del user.email_addresses[i] if obj: obj.delete() if new_addr.get('claim') or new_addr.get('addr'): user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='') # Clear password reset token claimed_emails_limit = config.get( 'user_prefs.maximum_claimed_emails', None) if claimed_emails_limit and len( user.email_addresses) >= int(claimed_emails_limit): flash( 'You cannot claim more than %s email addresses.' % claimed_emails_limit, 'error') return if not admin and (not kw.get('password') or not provider.validate_password( user, kw.get('password'))): flash( 'You must provide your current password to claim new email', 'error') return claimed_emails = M.EmailAddress.find({ 'email': new_addr['addr'] }).all() if any(email.claimed_by_user_id == user._id for email in claimed_emails): flash('Email address already claimed', 'error') elif mail_util.isvalid(new_addr['addr']): em = M.EmailAddress.create(new_addr['addr']) if em: user.email_addresses.append(em.email) em.claimed_by_user_id = user._id confirmed_emails = filter(lambda email: email.confirmed, claimed_emails) if not confirmed_emails: if not admin: em.send_verification_link() else: AuthController()._verify_addr(em) else: em.send_claim_attempt() if not admin: user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='') flash( 'A verification email has been sent. Please check your email and click to confirm.' ) h.auditlog_user('New email address: %s', new_addr['addr'], user=user) else: flash('Email address %s is invalid' % new_addr['addr'], 'error') else: flash('Email address %s is invalid' % new_addr['addr'], 'error') if not primary_addr and not user.get_pref( 'email_address') and user.email_addresses: primary_addr = select_new_primary_addr(user) if primary_addr: if user.get_pref('email_address') != primary_addr: if not admin and (not kw.get('password') or not provider.validate_password( user, kw.get('password'))): flash( 'You must provide your current password to change primary address', 'error') return h.auditlog_user('Primary email changed: %s => %s', user.get_pref('email_address'), primary_addr, user=user) user.set_pref('email_address', primary_addr) user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')
def _update_emails(self, user, admin=False, form_params={}): # not using **kw in method signature, to ensure 'admin' can't be passed in via a form submit kw = form_params addr = kw.pop('addr', None) new_addr = kw.pop('new_addr', None) primary_addr = kw.pop('primary_addr', None) provider = plugin.AuthenticationProvider.get(request) for i, (old_a, data) in enumerate(zip(user.email_addresses, addr or [])): obj = user.address_object(old_a) if data.get('delete') or not obj: if not admin and (not kw.get('password') or not provider.validate_password(user, kw.get('password'))): flash('You must provide your current password to delete an email', 'error') return if primary_addr == user.email_addresses[i]: if select_new_primary_addr(user, ignore_emails=primary_addr) is None \ and asbool(config.get('auth.require_email_addr', False)): flash('You must have at least one verified email address.', 'error') return else: # clear it now, a new one will get set below user.set_pref('email_address', None) primary_addr = None user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='') h.auditlog_user('Email address deleted: %s', user.email_addresses[i], user=user) del user.email_addresses[i] if obj: obj.delete() if new_addr.get('claim') or new_addr.get('addr'): user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='') # Clear password reset token claimed_emails_limit = config.get('user_prefs.maximum_claimed_emails', None) if claimed_emails_limit and len(user.email_addresses) >= int(claimed_emails_limit): flash('You cannot claim more than %s email addresses.' % claimed_emails_limit, 'error') return if not admin and (not kw.get('password') or not provider.validate_password(user, kw.get('password'))): flash('You must provide your current password to claim new email', 'error') return claimed_emails = M.EmailAddress.find({'email': new_addr['addr']}).all() if any(email.claimed_by_user_id == user._id for email in claimed_emails): flash('Email address already claimed', 'error') elif mail_util.isvalid(new_addr['addr']): em = M.EmailAddress.create(new_addr['addr']) if em: user.email_addresses.append(em.email) em.claimed_by_user_id = user._id confirmed_emails = filter(lambda email: email.confirmed, claimed_emails) if not confirmed_emails: if not admin: em.send_verification_link() else: AuthController()._verify_addr(em) else: em.send_claim_attempt() if not admin: user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='') flash('A verification email has been sent. Please check your email and click to confirm.') h.auditlog_user('New email address: %s', new_addr['addr'], user=user) else: flash('Email address %s is invalid' % new_addr['addr'], 'error') else: flash('Email address %s is invalid' % new_addr['addr'], 'error') if not primary_addr and not user.get_pref('email_address') and user.email_addresses: primary_addr = select_new_primary_addr(user) if primary_addr: if user.get_pref('email_address') != primary_addr: if not admin and (not kw.get('password') or not provider.validate_password(user, kw.get('password'))): flash('You must provide your current password to change primary address', 'error') return h.auditlog_user( 'Primary email changed: %s => %s', user.get_pref('email_address'), primary_addr, user=user) user.set_pref('email_address', primary_addr) user.set_tool_data('AuthPasswordReset', hash='', hash_expiry='')