def render_gdpr_update(to_email): params = { 'subscriber': get_or_save_email_subscriber(to_email, 'internal'), 'terms_of_use_link': 'https://gitcoin.co/legal/terms', 'privacy_policy_link': 'https://gitcoin.co/legal/privacy', 'cookie_policy_link': 'https://gitcoin.co/legal/cookie', } subject = "Gitcoin: Updated Terms & Policies" response_html = premailer_transform( render_to_string("emails/gdpr_update.html", params)) response_txt = render_to_string("emails/gdpr_update.txt", params) return response_html, response_txt, subject
def render_start_work_rejected(interest, bounty): to_email = interest.profile.email params = { 'subscriber': get_or_save_email_subscriber(to_email, 'internal'), 'interest': interest, 'bounty': bounty, 'approve_worker_url': bounty.approve_worker_url(interest.profile.handle), } subject = "Work Request Denied" response_html = premailer_transform(render_to_string("emails/start_work_rejected.html", params)) response_txt = render_to_string("emails/start_work_rejected.txt", params) return response_html, response_txt, subject
def render_faucet_rejected(fr): params = { 'fr': fr, 'amount': settings.FAUCET_AMOUNT, 'subscriber': get_or_save_email_subscriber(fr.email, 'internal'), } response_html = premailer_transform( render_to_string("emails/faucet_request_rejected.html", params)) response_txt = render_to_string("emails/faucet_request_rejected.txt", params) return response_html, response_txt
def render_start_work_applicant_expired(interest, bounty): to_email = bounty.bounty_owner_email params = { 'subscriber': get_or_save_email_subscriber(to_email, 'internal'), 'interest': interest, 'bounty': bounty, 'approve_worker_url': bounty.approve_worker_url(interest.profile.handle), } subject = "A Worker was Auto Approved" response_html = premailer_transform(render_to_string("emails/start_work_applicant_expired.html", params)) response_txt = render_to_string("emails/start_work_applicant_expired.txt", params) return response_html, response_txt, subject
def render_start_work_new_applicant(interest, bounty): to_email = bounty.bounty_owner_email params = { 'subscriber': get_or_save_email_subscriber(to_email, 'internal'), 'interest': interest, 'bounty': bounty, 'approve_worker_url': bounty.approve_worker_url(interest.profile.handle), } subject = "A new request to work on your bounty" response_html = premailer_transform(render_to_string("emails/start_work_new_applicant.html", params)) response_txt = render_to_string("emails/start_work_new_applicant.txt", params) return response_html, response_txt, subject
def slack(request): context = {} if request.POST.get('email', False): email = request.POST['email'] valid_email = True try: validate_email(request.POST.get('email', False)) except Exception as e: valid_email = False if valid_email: sc = SlackClient(settings.SLACK_TOKEN) response = sc.api_call('users.admin.invite', email=email) get_or_save_email_subscriber(email, 'slack') if response['ok']: context['msg'] = "Your invite has been sent. " else: context['msg'] = response['error'] else: context['msg'] = "Invalid email" return TemplateResponse(request, 'slack.html', context)
def render_new_bounty(to_email, bounties, old_bounties): sub = get_or_save_email_subscriber(to_email, 'internal') params = { 'old_bounties': old_bounties, 'bounties': bounties, 'subscriber': sub, 'keywords': ",".join(sub.keywords), } response_html = premailer_transform( render_to_string("emails/new_bounty.html", params)) response_txt = render_to_string("emails/new_bounty.txt", params) return response_html, response_txt
def handle(self, *args, **options): sc = SlackClient(settings.SLACK_TOKEN) ul = sc.api_call("users.list") # accepted invites for member in ul['members']: try: email = member['profile']['email'] get_or_save_email_subscriber(email, 'slack_ingester') except Exception: pass # pennding invites # get from https://gitcoincommunity.slack.com/admin/invites#pending # open chrome insepctor # look for 'invites' call # download that file, save as response.json # delete all lines except for the pending invites json blob import json filename = 'response.json' with open(filename, 'r') as f: members = json.load(f) for member in members: get_or_save_email_subscriber(email, 'slack_ingester')
def slack(request): email = request.POST.get('email') context = { 'active': 'slack', 'msg': 'You must provide an email address', } if email: context['msg'] = 'Your invite has been sent. ' try: validate_email(email) get_or_save_email_subscriber(email, 'slack', send_slack_invite=False) response = invite_to_slack(email) if not response.get('ok'): context['msg'] = response.get('error', 'Unknown error') rollbar.report_message( 'Slack invitation failed', 'warning', extra_data={'slack_response': response}) except ValidationError: context['msg'] = 'Invalid email' return TemplateResponse(request, 'slack.html', context)
def send_mail(from_email, to_email, subject, body, html=False, from_name="Gitcoin.co", cc_emails=None): # make sure this subscriber is saved get_or_save_email_subscriber(to_email, 'internal') # debug logs print("-- Sending Mail '{}' to {}".format(subject, to_email)) # setup sg = sendgrid.SendGridAPIClient(apikey=settings.SENDGRID_API_KEY) from_email = Email(from_email, from_name) to_email = Email(to_email) contenttype = "text/plain" if not html else "text/html" # build content content = Content(contenttype, html) if html else Content(contenttype, body) if settings.DEBUG: to_email = Email(settings.CONTACT_EMAIL) #just to be double secret sure of what were doing in dev subject = "[DEBUG] " + subject mail = Mail(from_email, subject, to_email, content) # build personalization (BCC + CC) p = Personalization() p.add_to(to_email) if cc_emails: #only add CCif not in prod for cc_addr in set(cc_emails): cc_addr = Email(cc_addr) if settings.DEBUG: cc_addr = to_email if cc_addr._email != to_email._email: p.add_to(cc_addr) p.add_bcc(Email(settings.BCC_EMAIL)) mail.add_personalization(p) # send mails response = sg.client.mail.send.post(request_body=mail.get()) return response
def sync_profile(handle, user=None, hide_profile=True): data = get_user(handle) email = '' is_error = 'name' not in data.keys() if is_error: print("- error main") logger.warning('Failed to fetch github username', exc_info=True, extra={'handle': handle}) return None defaults = {'last_sync_date': timezone.now(), 'data': data, 'hide_profile': hide_profile, } if user and isinstance(user, User): defaults['user'] = user try: defaults['github_access_token'] = user.social_auth.filter(provider='github').latest('pk').access_token if user and user.email: defaults['email'] = user.email except UserSocialAuth.DoesNotExist: pass # store the org info in postgres try: profile, created = Profile.objects.update_or_create(handle=handle, defaults=defaults) print("Profile:", profile, "- created" if created else "- updated") except Exception as e: logger.error(e) return None if user and user.email: email = user.email elif profile and profile.email: email = profile.email if email and profile: get_or_save_email_subscriber(email, 'sync_profile', profile=profile) return profile
def slack(request): context = { 'active': 'slack', 'msg': None, } if request.POST: email = request.POST.get('email') context['msg'] = _('You must provide an email address') if email: context['msg'] = _('Your invite has been sent.') context['success'] = True try: validate_email(email) get_or_save_email_subscriber(email, 'slack', send_slack_invite=False) response = invite_to_slack(email) if not response.get('ok'): context['msg'] = response.get('error', _('Unknown error')) context['success'] = False except ValidationError: context['msg'] = _('Invalid email') return TemplateResponse(request, 'slack.html', context)
def slack(request): context = { 'active': 'slack', } if request.POST.get('email', False): email = request.POST['email'] valid_email = True try: validate_email(request.POST.get('email', False)) except ValidationError: valid_email = False if valid_email: get_or_save_email_subscriber(email, 'slack') response = invite_to_slack(email) if response['ok']: context['msg'] = "Your invite has been sent. " else: context['msg'] = response['error'] else: context['msg'] = "Invalid email" return TemplateResponse(request, 'slack.html', context)
def render_bounty_startwork_expire_warning(to_email, bounty, interest, time_delta_days): params = { 'bounty': bounty, 'interest': interest, 'time_delta_days': time_delta_days, 'subscriber': get_or_save_email_subscriber(to_email, 'internal'), } response_html = premailer_transform( render_to_string("emails/bounty_startwork_expire_warning.html", params)) response_txt = render_to_string( "emails/bounty_startwork_expire_warning.txt", params) return response_html, response_txt
def render_new_bounty(to_email, bounties, old_bounties, offset=3): email_style = (int(timezone.now().strftime("%-j")) + offset) % 24 sub = get_or_save_email_subscriber(to_email, 'internal') params = { 'old_bounties': old_bounties, 'bounties': bounties, 'subscriber': sub, 'keywords': ",".join(sub.keywords) if sub and sub.keywords else '', 'email_style': email_style, 'email_type': 'new_bounty_notifications' } response_html = premailer_transform(render_to_string("emails/new_bounty.html", params)) response_txt = render_to_string("emails/new_bounty.txt", params) return response_html, response_txt
def email_settings(request, key): email = '' level = '' msg = '' es = EmailSubscriber.objects.filter(priv=key) if es.exists(): email = es.first().email level = es.first().preferences.get('level', False) if request.POST.get('email', False): level = request.POST.get('level') comments = request.POST.get('comments')[:255] email = request.POST.get('email') print(email) validation_passed = True try: validate_email(email) except Exception as e: print(e) validation_passed = False msg = 'Invalid Email' if level not in ['lite', 'regular', 'nothing']: validation_passed = False msg = 'Invalid Level' if validation_passed: key = get_or_save_email_subscriber(email, 'settings') es = EmailSubscriber.objects.get(priv=key) es.preferences['level'] = level es.metadata['comments'] = comments ip = get_ip(request) es.active = level != 'nothing' es.newsletter = level == 'regular' if not es.metadata.get('ip', False): es.metadata['ip'] = [ip] else: es.metadata['ip'].append(ip) es.save() msg = "Updated your preferences. " context = { 'email': email, 'level': level, 'msg': msg, } return TemplateResponse(request, 'email_settings.html', context)
def render_nth_day_email_campaign(to_email, nth, firstname): subject_map = { 1: "Day 1: Growing Open Source", 2: "Day 2: Using Gitcoin's Issue Explorer", 3: "Learning Blockchain" } subject = subject_map[nth] params = { "firstname": firstname, "subscriber": get_or_save_email_subscriber(to_email, "internal"), } response_html = premailer_transform(render_to_string(f"emails/campaigns/email_campaign_day_{nth}.html", params)) response_txt = render_to_string(f"emails/campaigns/email_campaign_day_{nth}.txt", params) return response_html, response_txt, subject
def settings_helper_get_auth(request, key=None): # setup github_handle = request.user.username if request.user.is_authenticated else False is_logged_in = bool(request.user.is_authenticated) es = EmailSubscriber.objects.none() # find the user info if key is None or not EmailSubscriber.objects.filter(priv=key).exists(): email = request.user.email if request.user.is_authenticated else None if not email: github_handle = request.user.username if request.user.is_authenticated else None if hasattr(request.user, 'profile'): if request.user.profile.email_subscriptions.exists(): es = request.user.profile.email_subscriptions.first() if not es or es and not es.priv: es = get_or_save_email_subscriber(request.user.email, 'settings', profile=request.user.profile) else: try: es = EmailSubscriber.objects.get(priv=key) email = es.email except EmailSubscriber.DoesNotExist: pass # lazily create profile if needed profiles = Profile.objects.none() if github_handle: profiles = Profile.objects.prefetch_related('alumni').filter( handle=github_handle.lower()) profile = None if not profiles.exists() else profiles.first() if not profile and github_handle: profile = sync_profile(github_handle, user=request.user) # lazily create email settings if needed if not es: if request.user.is_authenticated and request.user.email: es = EmailSubscriber.objects.create( email=request.user.email, source='settings_page', profile=request.user.profile, ) es.set_priv() es.save() return profile, es, request.user, is_logged_in
def render_new_bounty_roundup(to_email): from dashboard.models import Bounty bounties = [ { 'obj': Bounty.objects.get( current_bounty=True, github_url='https://github.com/gitcoinco/web/issues/221'), 'primer': 'Gitcoin is built using Gitcoin. Want to help out and get paid? 💯 ~ @owocki', }, { 'obj': Bounty.objects.get( current_bounty=True, github_url= 'https://github.com/ProjectWyvern/dao.projectwyvern.com/issues/1' ), 'primer': 'Here is a fun little solidity programming scope.. Great way to learn (and get paid for it!) ~ @owocki', }, { 'obj': Bounty.objects.get( current_bounty=True, github_url='https://github.com/browep/brower-walk/issues/1'), 'primer': 'Into graphics programming? This issue could be for you.. ~ @owocki', }, ] params = { 'bounties': bounties, 'override_back_color': '#15003e', 'invert_footer': True, 'hide_header': True, 'subscriber_id': get_or_save_email_subscriber(to_email, 'internal'), } response_html = premailer_transform( render_to_string("emails/bounty_roundup.html", params)) response_txt = render_to_string("emails/bounty_roundup.txt", params) return response_html, response_txt
def render_new_bounty_roundup(to_email): from dashboard.models import Bounty bounties = [ { 'obj': Bounty.objects.get( current_bounty=True, github_url='https://github.com/ethereum/web3.py/issues/549'), 'primer': 'This is a python issue for the Ethereum Foundation... 💯 ~ @owocki', }, { 'obj': Bounty.objects.get( current_bounty=True, github_url='https://github.com/gitcoinco/web/issues/208'), 'primer': 'Want to help build Gitcoin? Here\'s an opppy to do just that 👇\' ~ @owocki', }, { 'obj': Bounty.objects.get( current_bounty=True, github_url='https://github.com/btcsuite/btcd/issues/1089'), 'primer': 'Into Bitcoin and distributed programming? This issue could be for you.. ~ @owocki', }, ] params = { 'bounties': bounties, 'override_back_color': '#15003e', 'invert_footer': True, 'hide_header': True, 'subscriber_id': get_or_save_email_subscriber(to_email, 'internal'), } response_html = premailer_transform( render_to_string("emails/bounty_roundup.html", params)) response_txt = render_to_string("emails/bounty_roundup.txt", params) return response_html, response_txt
def render_tip_email(to_email, tip, is_new): warning = tip.network if tip.network != 'mainnet' else "" already_redeemed = bool(tip.receive_txid) link = tip.url if tip.web3_type != 'v2': link = tip.receive_url elif tip.web3_type != 'v3': link = tip.receive_url_for_recipient params = { 'link': link, 'amount': round(tip.amount, 5), 'tokenName': tip.tokenName, 'comments_priv': tip.comments_priv, 'comments_public': tip.comments_public, 'tip': tip, 'already_redeemed': already_redeemed, 'show_expires': not already_redeemed and tip.expires_date < (timezone.now() + timezone.timedelta(days=365)) and tip.expires_date, 'is_new': is_new, 'warning': warning, 'subscriber': get_or_save_email_subscriber(to_email, 'internal'), 'is_sender': to_email not in tip.emails, 'is_receiver': to_email in tip.emails, } response_html = premailer_transform( render_to_string("emails/new_tip.html", params)) response_txt = render_to_string("emails/new_tip.txt", params) return response_html, response_txt
def render_new_bounty_roundup(to_email): from dashboard.models import Bounty bounties = [ { 'obj': Bounty.objects.get(pk=187), 'primer': 'Get paid to help your friends get paid. And disrupt recruing while you\'re at it! 💯 ~ @owocki', }, { 'obj': Bounty.objects.get(pk=159), 'primer': 'Got Linux chops? This Funded issue is you for. ~ @owocki', }, { 'obj': Bounty.objects.get(pk=120), 'primer': 'Performance is a feature. And Truffle is a hugely important piece of web3 infrastructure. Earn 2 ETH to pushing it forward. ~ @owocki', }, { 'obj': Bounty.objects.get(pk=126), 'primer': 'Python dev? Here\'s an oppy to make an impact on web3py ~ @owocki', }, ] params = { 'bounties': bounties, 'override_back_color': '#15003e', 'invert_footer': True, 'hide_header': True, 'subscriber_id': get_or_save_email_subscriber(to_email, 'internal'), } response_html = premailer_transform( render_to_string("emails/bounty_roundup.html", params)) response_txt = render_to_string("emails/bounty_roundup.txt", params) return response_html, response_txt
def render_new_bounty_roundup(to_email): from dashboard.models import Bounty bounties = [ { 'obj': Bounty.objects.get(pk=328), 'primer': 'Into Design? Help Gitcoin articulate our mission, culture, and values. 💯 ~ @owocki', }, { 'obj': Bounty.objects.get(pk=301), 'primer': 'Got Solidity chops? Into Testing? This Funded issue is you for. ~ @owocki', }, { 'obj': Bounty.objects.get(pk=118), 'primer': 'Security and documentation task below. Good oppy to meet some of the web3 security folks out there. ~ @owocki', }, { 'obj': Bounty.objects.get(pk=159), 'primer': 'Linux head? This issue is for you! 👇 ~ @owocki', }, ] params = { 'bounties': bounties, 'override_back_color': '#15003e', 'invert_footer': True, 'hide_header': True, 'subscriber_id': get_or_save_email_subscriber(to_email, 'internal'), } response_html = premailer_transform( render_to_string("emails/bounty_roundup.html", params)) response_txt = render_to_string("emails/bounty_roundup.txt", params) return response_html, response_txt
def render_bounty_expire_warning(to_email, bounty): unit = 'days' num = int(round((bounty.expires_date - timezone.now()).days, 0)) if num == 0: unit = 'hours' num = int(round((bounty.expires_date - timezone.now()).seconds / 3600 / 24, 0)) params = { 'bounty': bounty, 'num': num, 'unit': unit, 'subscriber_id': get_or_save_email_subscriber(to_email, 'internal'), 'is_claimee': (bounty.claimee_email if bounty.claimee_email else "").lower() == to_email.lower(), 'is_owner': bounty.bounty_owner_email.lower() == to_email.lower(), } response_html = premailer_transform(render_to_string("emails/new_bounty_expire_warning.html", params)) response_txt = render_to_string("emails/new_bounty_expire_warning.txt", params) return response_html, response_txt
def render_tip_email(to_email, tip, is_new): warning = tip.network if tip.network != 'mainnet' else "" params = { 'link': tip.url, 'amount': round(tip.amount, 5), 'tokenName': tip.tokenName, 'comments_priv': tip.comments_priv, 'comments_public': tip.comments_public, 'tip': tip, 'show_expires': tip.expires_date < (timezone.now() + timezone.timedelta(days=365)), 'is_new': is_new, 'warning': warning, 'subscriber_id': get_or_save_email_subscriber(to_email, 'internal'), 'is_sender': to_email not in tip.emails, 'is_receiver': to_email in tip.emails, } response_html = premailer_transform(render_to_string("emails/new_tip.html", params)) response_txt = render_to_string("emails/new_tip.txt", params) return response_html, response_txt
def render_kudos_email(to_email, kudos_transfer, is_new, html_template, text_template=None): """Summary Args: to_emails (list): An array of email addresses to send the email to. kudos_transfer (model): An instance of the `kudos.model.KudosTransfer` object. This contains the information about the kudos that will be cloned. is_new (TYPE): Description Returns: tup: response_html, response_txt """ warning = kudos_transfer.network if kudos_transfer.network != 'mainnet' else "" already_redeemed = bool(kudos_transfer.receive_txid) link = kudos_transfer.receive_url_for_recipient params = { 'link': link, 'amount': round(kudos_transfer.amount, 5), 'token_elem': kudos_transfer.kudos_token or kudos_transfer.kudos_token_cloned_from, 'kudos_token:': kudos_transfer.kudos_token, 'comments_public': kudos_transfer.comments_public, 'kudos_transfer': kudos_transfer, 'already_redeemed': already_redeemed, 'is_new': is_new, 'warning': warning, 'subscriber': get_or_save_email_subscriber(to_email, 'internal'), 'is_sender': to_email not in kudos_transfer.emails, 'is_receiver': to_email in kudos_transfer.emails, } response_html = premailer_transform(render_to_string( html_template, params)) response_txt = render_to_string(text_template, params) if text_template else None return response_html, response_txt
def render_unread_notification_email_weekly_roundup(to_email, from_date=date.today(), days_ago=7): subscriber = get_or_save_email_subscriber(to_email, 'internal') from dashboard.models import Profile from inbox.models import Notification profile = Profile.objects.filter(email__iexact=to_email).last() from_date = from_date + timedelta(days=1) to_date = from_date - timedelta(days=days_ago) notifications = Notification.objects.filter(to_user=profile.id, is_read=False, created_on__range=[to_date, from_date]).count() params = { 'subscriber': subscriber, 'profile': profile.handle, 'notifications': notifications, } subject = "Your unread notifications" response_html = premailer_transform(render_to_string("emails/unread_notifications_roundup/unread_notification_email_weekly_roundup.html", params)) response_txt = render_to_string("emails/unread_notifications_roundup/unread_notification_email_weekly_roundup.txt", params) return response_html, response_txt, subject
def render_new_bounty_roundup(to_email): from dashboard.models import Bounty bounties = [ { 'obj': Bounty.objects.get(pk=387), 'primer': 'Truffle is 💯 Here\'s an oppy to contribute to their project! ~ @owocki', }, { 'obj': Bounty.objects.get(pk=297), 'primer': 'Get paid for work in the intersection of VR / Open Source ~ @owocki', }, { 'obj': Bounty.objects.get(pk=118), 'primer': 'Security and documentation task below. Good oppy to meet some of the web3 security folks out there. ~ @owocki', }, ] params = { 'bounties': bounties, 'override_back_color': '#15003e', 'invert_footer': True, 'hide_header': True, 'subscriber_id': get_or_save_email_subscriber(to_email, 'internal'), } response_html = premailer_transform( render_to_string("emails/bounty_roundup.html", params)) response_txt = render_to_string("emails/bounty_roundup.txt", params) return response_html, response_txt
def render_new_bounty_roundup(to_email): from dashboard.models import Bounty bounties = [ { 'obj': Bounty.objects.get(pk=127), 'primer': 'Piper Merriam is the force in open source. Know python? This issue is for you.', }, { 'obj': Bounty.objects.get(pk=120), 'primer': 'Truffle is one of the most popular web3 development tools. Heres an oppy to help them increase their speed', }, { 'obj': Bounty.objects.get(pk=168), 'primer': 'Here\'s an opportunity to recruit your friends and earn some ETH. (Recruiter Spammers need not apply!)', }, ] params = { 'bounties': bounties, 'override_back_color': '#15003e', 'invert_footer': True, 'hide_header': True, 'subscriber_id': get_or_save_email_subscriber(to_email, 'internal'), } response_html = premailer_transform( render_to_string("emails/bounty_roundup.html", params)) response_txt = render_to_string("emails/bounty_roundup.txt", params) return response_html, response_txt
def render_bounty_expire_warning(to_email, bounty): from django.db.models.functions import Lower unit = 'days' num = int(round((bounty.expires_date - timezone.now()).days, 0)) if num == 0: unit = 'hours' num = int(round((bounty.expires_date - timezone.now()).seconds / 3600 / 24, 0)) fulfiller_emails = list(bounty.fulfillments.annotate(lower_email=Lower('fulfiller_email')).values_list('lower_email')) params = { 'bounty': bounty, 'num': num, 'unit': unit, 'is_claimee': (to_email.lower() in fulfiller_emails), 'is_owner': bounty.bounty_owner_email.lower() == to_email.lower(), 'subscriber': get_or_save_email_subscriber(to_email, 'internal'), } response_html = premailer_transform(render_to_string("emails/new_bounty_expire_warning.html", params)) response_txt = render_to_string("emails/new_bounty_expire_warning.txt", params) return response_html, response_txt