def send_linked_domain_release_email(results, master_domain, username, models, linked_domains): manager = ReleaseManager(master_domain, username) # chord sends a list of results only if there were multiple tasks if len(linked_domains) == 1: results = [results] for result in results: (successes, errors) = result manager.update_successes(successes) manager.update_errors(errors) subject = _("Linked project release complete.") if manager.get_error_domain_count(): subject += _(" Errors occurred.") email = manager.user.email or manager.user.username send_html_email_async(subject, email, manager.get_email_message(models, linked_domains, html=True), text_content=manager.get_email_message( models, linked_domains, html=False), email_from=settings.DEFAULT_FROM_EMAIL)
def email_enterprise_report(domain, slug, couch_user): account = BillingAccount.get_account_by_domain(domain) report = EnterpriseReport.create(slug, account.id, couch_user) # Generate file csv_file = io.StringIO() writer = csv.writer(csv_file) writer.writerow(report.headers) writer.writerows(report.rows) # Store file in redis hash_id = uuid.uuid4().hex redis = get_redis_client() redis.set(hash_id, csv_file.getvalue()) redis.expire(hash_id, 60 * 60 * 24) csv_file.close() # Send email url = absolute_reverse("enterprise_dashboard_download", args=[domain, report.slug, str(hash_id)]) link = "<a href='{}'>{}</a>".format(url, url) subject = _("Enterprise Dashboard: {}").format(report.title) body = "The enterprise report you requested for the account {} is ready.<br>" \ "You can download the data at the following link: {}<br><br>" \ "Please remember that this link will only be active for 24 hours.".format(account.name, link) send_html_email_async(subject, couch_user.username, body)
def email_enterprise_report(domain, slug, couch_user): account = BillingAccount.get_account_by_domain(domain) report = EnterpriseReport.create(slug, account.id, couch_user) # Generate file csv_file = io.StringIO() writer = csv.writer(csv_file) writer.writerow(report.headers) writer.writerows(report.rows) # Store file in redis hash_id = uuid.uuid4().hex redis = get_redis_client() redis.set(hash_id, csv_file.getvalue()) redis.expire(hash_id, 60 * 60 * 24) csv_file.close() # Send email url = absolute_reverse("enterprise_dashboard_download", args=[domain, report.slug, str(hash_id)]) link = "<a href='{}'>{}</a>".format(url, url) subject = _("Enterprise Dashboard: {}").format(report.title) body = "The enterprise report you requested for the account {} is ready.<br>" \ "You can download the data at the following link: {}<br><br>" \ "Please remember that this link will only be active for 24 hours.".format(account.name, link) send_html_email_async(subject, couch_user.username, body)
def handle(self, account_id, username, **kwargs): self.couch_user = CouchUser.get_by_username(username) self.account_id = account_id if not self.couch_user: raise CommandError("Option: '--username' must be specified") self.now = datetime.utcnow() account = BillingAccount.objects.get(id=account_id) message = '' if kwargs.get('message'): message += kwargs.get('message') + "\n" message += "Report run {}\n".format(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')) attachments = [] for slug in ( EnterpriseReport.DOMAINS, EnterpriseReport.WEB_USERS, EnterpriseReport.MOBILE_USERS, EnterpriseReport.FORM_SUBMISSIONS, ): (attachment, count) = self._write_file(slug) attachments.append(attachment) message += "{}: {}\n".format(slug, count) cc = [] if kwargs.get('cc'): cc = kwargs.get('cc').split(",") send_html_email_async( "Report on enterprise account {}".format(account.name), self.couch_user.username, linebreaksbr(message), cc=cc, text_content=message, file_attachments=attachments, ) print('Emailed {}{}{}'.format(self.couch_user.username, " and " if cc else "", ", ".join(cc)))
def send_mass_emails(username, real_email, subject, html, text): if real_email: recipients = [{ 'username': h['username'], 'first_name': h['first_name'] or 'CommCare User', } for h in UserES().web_users().run().hits] else: recipients = [{ 'username': username, 'first_name': 'CommCare User', }] successes = [] failures = [] for recipient in recipients: context = recipient context.update({ 'url_prefix': '' if settings.STATIC_CDN else 'http://' + get_site_domain(), }) html_template = Template(html) text_template = Template(text) text_content = render_to_string( "hqadmin/email/mass_email_base.txt", { 'email_body': text_template.render(Context(context)), }) html_content = render_to_string( "hqadmin/email/mass_email_base.html", { 'email_body': html_template.render(Context(context)), }) try: send_HTML_email(subject, recipient['username'], html_content, text_content=text_content) successes.append((recipient['username'], None)) except Exception as e: failures.append((recipient['username'], e)) message = ( "Subject: {subject},\n" "Total successes: {success_count} \n Total errors: {failure_count} \n" "".format(subject=subject, success_count=len(successes), failure_count=len(failures))) send_html_email_async("Mass email summary", username, message, text_content=message, file_attachments=[ _mass_email_attachment('successes', successes), _mass_email_attachment('failures', failures) ])
def send_abnormal_usage_alert(alert): """ Sends an alert to #support and email to let support know when a domain is doing something weird :param alert: AbnormalUsageAlert object """ subject = "{domain} is doing something interesting with the {source} in the {environment} env".format( domain=alert.domain, source=alert.source, environment=settings.SERVER_ENVIRONMENT) send_html_email_async(subject, support_email, alert.message)
def send_status_email(domain, async_result): errors = [] duration = datetime.timedelta() updates = 0 noupdates = 0 batch_info_template = "Batch {index}: Completed in {duration}. Errors: {errors}. Updates: {updates}\n" batch_info_message = "" for i, batch_info in enumerate(async_result): errors += batch_info.errors duration += batch_info.duration updates += batch_info.update_count noupdates += batch_info.noupdate_count batch_info_message += batch_info_template.format( index=i + 1, duration=batch_info.duration, updates=batch_info.update_count, errors=len(batch_info.errors), ) subject = "eNikshay Episode Task results for: {}".format( datetime.date.today()) recipient = "{}@{}.{}".format('commcarehq-ops+admins', 'dimagi', 'com') cc = "{}@{}.{}".format('frener', 'dimagi', 'com') csv_file = io.BytesIO() writer = UnicodeWriter(csv_file) writer.writerow(['Episode ID', 'Domain', 'Updater Class', 'Error']) writer.writerows(errors) message = ( "domain: {domain},\n Summary: \n " "total duration: {duration} \n" "total updates: {updates} \n total errors: {errors} \n total non-updates: {noupdates} \n" "".format(domain=domain, duration=duration, updates=updates, errors=len(errors), noupdates=noupdates)) message += batch_info_message attachment = { 'title': "failed_episodes_{}.csv".format(datetime.date.today()), 'mimetype': 'text/csv', 'file_obj': csv_file, } send_html_email_async(subject, recipient, message, cc=[cc], text_content=message, file_attachments=[attachment])
def send_mass_emails(username, real_email, subject, html, text): if real_email: recipients = [{ 'username': h['username'], 'first_name': h['first_name'] or 'CommCare User', } for h in UserES().web_users().run().hits] else: recipients = [{ 'username': username, 'first_name': 'CommCare User', }] successes = [] failures = [] for recipient in recipients: context = recipient context.update({ 'url_prefix': '' if settings.STATIC_CDN else 'http://' + get_site_domain(), }) html_template = Template(html) text_template = Template(text) text_content = render_to_string("hqadmin/email/mass_email_base.txt", { 'email_body': text_template.render(Context(context)), }) html_content = render_to_string("hqadmin/email/mass_email_base.html", { 'email_body': html_template.render(Context(context)), }) try: send_HTML_email(subject, recipient['username'], html_content, text_content=text_content) successes.append((recipient['username'], None)) except Exception as e: failures.append((recipient['username'], e)) message = ( "Subject: {subject},\n" "Total successes: {success_count} \n Total errors: {failure_count} \n" "".format( subject=subject, success_count=len(successes), failure_count=len(failures)) ) send_html_email_async( "Mass email summary", username, message, text_content=message, file_attachments=[ _mass_email_attachment('successes', successes), _mass_email_attachment('failures', failures)] )
def send_abnormal_usage_alert(alert): """ Sends an alert to #support and email to let support know when a domain is doing something weird :param alert: AbnormalUsageAlert object """ subject = "{domain} is doing something interesting with the {source} in the {environment} env".format( domain=alert.domain, source=alert.source, environment=settings.SERVER_ENVIRONMENT ) send_html_email_async( subject, support_email, alert.message )
def send_abnormal_usage_alert(alert): """ Sends an alert to #support and email to let support know when a domain is doing something weird :param alert: AbnormalUsageAlert object """ subject = "{domain} is doing something interesting with the {source} in the {environment} env".format( domain=alert.domain, source=alert.source, environment=settings.SERVER_ENVIRONMENT) send_html_email_async(subject, support_email, alert.message) if hasattr(settings, 'MIA_THE_DEPLOY_BOT_API'): requests.post(settings.MIA_THE_DEPLOY_BOT_API, data=json.dumps({ "channel": slack_channel, "username": "******", "text": subject }))
def send_status_email(domain, async_result): errors = [] duration = datetime.timedelta() updates = 0 noupdates = 0 for batch_info in async_result: errors += batch_info.errors duration += batch_info.duration updates += batch_info.update_count noupdates += batch_info.noupdate_count subject = "eNikshay Episode Task results for: {}".format( datetime.date.today()) recipient = "{}@{}.{}".format('commcarehq-ops+admins', 'dimagi', 'com') cc = "{}@{}.{}".format('frener', 'dimagi', 'com') csv_file = StringIO() writer = UnicodeWriter(csv_file) writer.writerow(['Episode ID', 'Domain', 'Updater Class', 'Error']) writer.writerows(errors) message = ( "Summary of enikshay_task: domain: {domain}, duration (sec): {duration} " "Cases Updated {updates}, cases errored {errors} and {noupdates} " "cases didn't need update. ".format(domain=domain, duration=duration, updates=updates, errors=len(errors), noupdates=noupdates)) attachment = { 'title': "failed_episodes_{}.csv".format(datetime.date.today()), 'mimetype': 'text/csv', 'file_obj': csv_file, } send_html_email_async(subject, recipient, message, cc=[cc], text_content=message, file_attachments=[attachment])
def _get_and_send_report(self, language, emails): from corehq.apps.reports.views import get_scheduled_report_response, render_full_report_notification with localize(language): title = (_(DEFAULT_REPORT_NOTIF_SUBJECT) if self.email_subject == DEFAULT_REPORT_NOTIF_SUBJECT else self.email_subject) attach_excel = getattr(self, 'attach_excel', False) try: content, excel_files = get_scheduled_report_response( self.owner, self.domain, self._id, attach_excel=attach_excel, send_only_active=True) # Will be False if ALL the ReportConfigs in the ReportNotification # have a start_date in the future. if content is False: return for email in emails: body = render_full_report_notification( None, content, email, self).content send_html_email_async( title, email, body, email_from=settings.DEFAULT_FROM_EMAIL, file_attachments=excel_files, smtp_exception_skip_list=LARGE_FILE_SIZE_ERROR_CODES) except Exception as er: notify_exception( None, message= "Encountered error while generating report or sending email", details={ 'subject': title, 'recipients': str(emails), 'error': er, }) if getattr(er, 'smtp_code', None) in LARGE_FILE_SIZE_ERROR_CODES or type( er) == ESError: # If the email doesn't work because it is too large to fit in the HTML body, # send it as an excel attachment, by creating a mock request with the right data. for report_config in self.configs: mock_request = HttpRequest() mock_request.couch_user = self.owner mock_request.user = self.owner.get_django_user() mock_request.domain = self.domain mock_request.couch_user.current_domain = self.domain mock_request.couch_user.language = self.language mock_request.method = 'GET' mock_request.bypass_two_factor = True mock_query_string_parts = [ report_config.query_string, 'filterSet=true' ] if report_config.is_configurable_report: mock_query_string_parts.append( urlencode(report_config.filters, True)) mock_query_string_parts.append( urlencode(report_config.get_date_range(), True)) mock_request.GET = QueryDict( '&'.join(mock_query_string_parts)) date_range = report_config.get_date_range() start_date = datetime.strptime(date_range['startdate'], '%Y-%m-%d') end_date = datetime.strptime(date_range['enddate'], '%Y-%m-%d') datespan = DateSpan(start_date, end_date) request_data = vars(mock_request) request_data[ 'couch_user'] = mock_request.couch_user.userID request_data['datespan'] = datespan full_request = { 'request': request_data, 'domain': request_data['domain'], 'context': {}, 'request_params': json_request(request_data['GET']) } export_all_rows_task(report_config.report, full_request, emails, title)
def handle(self, account_id, username, **kwargs): self.couch_user = CouchUser.get_by_username(username) self.window = 7 if not self.couch_user: raise CommandError("Option: '--username' must be specified") self.now = datetime.utcnow() account = BillingAccount.objects.get(id=account_id) subscriptions = Subscription.visible_objects.filter( account_id=account.id, is_active=True) self.domain_names = set(s.subscriber.domain for s in subscriptions) print('Found {} domains for {}'.format(len(self.domain_names), account.name)) domain_headers = ['Project Space Name', 'Project Name', 'Project URL'] headers = domain_headers + [ 'Plan', '# of Mobile Users', '# of Web Users' ] (domain_file, domain_count) = self._write_file('domains', headers, self._domain_rows) headers = ['Name', 'Email Address', 'Role', 'Last Login' ] + domain_headers (web_user_file, web_user_count) = self._write_file('web_users', headers, self._web_user_rows) headers = [ 'Username', 'Name', 'Last Sync', 'Last Submission', 'CommCare Version' ] + domain_headers (mobile_user_file, mobile_user_count) = self._write_file('mobile_users', headers, self._mobile_user_rows) headers = ['Form Name', 'Submitted', 'App Name', 'Mobile User' ] + domain_headers (form_file, form_count) = self._write_file('forms', headers, self._form_rows) message = ('''{message} Report run {timestamp} Domains: {domain_count} Web Users: {web_user_count} Mobile Users: {mobile_user_count} Forms from past {window} days: {form_count} '''.format( **{ 'message': kwargs.get('message') or '', 'domain_count': domain_count, 'web_user_count': web_user_count, 'mobile_user_count': mobile_user_count, 'window': self.window, 'form_count': form_count, 'timestamp': self.now.strftime('%Y-%m-%d %H:%M:%S'), })) cc = [] if kwargs.get('cc'): cc = kwargs.get('cc').split(",") send_html_email_async("Report on enterprise account {}".format( account.name), self.couch_user.username, linebreaksbr(message), cc=cc, text_content=message, file_attachments=[ domain_file, web_user_file, mobile_user_file, form_file, ]) print('Emailed {}{}{}'.format(self.couch_user.username, " and " if cc else "", ", ".join(cc)))