def save(self, domain_override=None, subject_template_name='registration/password_reset_subject.txt', email_template_name='registration/password_reset_email.html', use_https=False, token_generator=default_token_generator, from_email=None, request=None): """ Cleaned save that doesn't do lots of stuff we don't need. Adds categories to emails and allows them to be html. """ email = self.cleaned_data['email'] user = User.objects.get_email_owner(email) if user is None: return c = { 'user': user, 'uid': urlsafe_base64_encode(force_bytes(user.pk)), 'token': token_generator.make_token(user) } headers = { 'X-SMTPAPI': '{"category": "Forgotten Password for User %s"}' % ( user.pk) } body = loader.render_to_string(email_template_name, c) send_email(body, email_type=settings.FORGOTTEN_PASSWORD, recipients=[email], headers=headers, domain=get_current_seosite('domain', 'lower'))
def send_activation_email(self, primary=True, password=None, custom_msg=None): if self.activation_key_expired(): self.reset_activation() if custom_msg: custom_msg = custom_msg.replace('\n', '<br>') custom_msg = mark_safe(custom_msg) ctx_dict = { 'activation_key': self.activation_key, 'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS, 'password': password, 'primary': primary, 'user': self.user, 'custom_msg': custom_msg } message = render_to_string('registration/activation_email.html', ctx_dict) message = Pynliner().from_string(message).run() site = getattr(settings, 'SITE', None) headers = { 'X-SMTPAPI': '{"category": "Activation sent (%s)"}' % self.pk } send_email(message, email_type=settings.ACTIVATION, recipients=[self.email], site=site, headers=headers)
def send_update_email(self, msg, custom_msg=None): """ This function is meant to be called from the shell. It sends a notice to the user that their saved search has been updated by the system or an admin. Inputs: :msg: The description of the update. Passed through verbatim to the template. Returns: nothing """ context_dict = { 'saved_searches': [(self,)], 'message': msg, 'custom_msg': custom_msg, 'contains_pss': hasattr(self, 'partnersavedsearch') } message = render_to_string("mysearches/email_update.html", context_dict) category = '{"category": "My.jobs Saved Search Updated (%s:%s)"}' % ( self.content_type, self.pk) headers = {'X-SMTPAPI': category} send_email(message, email_type=settings.SAVED_SEARCH_UPDATED, recipients=[self.email], label=self.label.strip(), headers=headers) SavedSearchLog.objects.create( reason='Jobs are not sent in saved search update emails', was_sent=True, was_received=False, recipient=self.user, recipient_email=self.email, new_jobs=0, backfill_jobs=0)
def send_activation_email(self, primary=True, password=None, custom_msg=None): if self.activation_key_expired(): self.reset_activation() if custom_msg: custom_msg = custom_msg.replace('\n', '<br>') custom_msg = mark_safe(custom_msg) ctx_dict = {'activation_key': self.activation_key, 'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS, 'password': password, 'primary': primary, 'user': self.user, 'custom_msg': custom_msg} message = render_to_string('registration/activation_email.html', ctx_dict) message = Pynliner().from_string(message).run() site = getattr(settings, 'SITE', None) headers = { 'X-SMTPAPI': '{"category": "Activation sent (%s)"}' % self.pk } send_email(message, email_type=settings.ACTIVATION, recipients=[self.email], site=site, headers=headers)
def save(self, domain_override=None, subject_template_name='registration/password_reset_subject.txt', email_template_name='registration/password_reset_email.html', use_https=False, token_generator=default_token_generator, from_email=None, request=None): """ Cleaned save that doesn't do lots of stuff we don't need. Adds categories to emails and allows them to be html. """ email = self.cleaned_data['email'] user = User.objects.get_email_owner(email) if user is None: return c = { 'user': user, 'uid': urlsafe_base64_encode(force_bytes(user.pk)), 'token': token_generator.make_token(user) } headers = { 'X-SMTPAPI': '{"category": "Forgotten Password for User %s"}' % ( user.pk) } body = loader.render_to_string(email_template_name, c) send_email(body, email_type=settings.FORGOTTEN_PASSWORD, recipients=[email], headers=headers, domain=get_current_seosite('domain', 'lower'))
def send_contact_record_email_response(created_records, created_contacts, attachment_failures, unmatched_contacts, error, to_email, is_nuo=False, company=None, buckets=None): # Multiple outreach email addresses may have been provided. We should have # already ensured that they all belong to one company. Pick one to use in # our return email. bucket = '' if buckets: bucket = buckets[0] ctx = { 'created_records': created_records, 'created_contacts': created_contacts, 'error': error, 'unmatched_contacts': unmatched_contacts, 'attachment_failures': attachment_failures, 'company': company, 'to_email': to_email, 'bucket': bucket, } template = 'mypartners/email/email_response.html' if is_nuo: template = 'mypartners/email/nuo_email_response.html' message = render_to_string(template, ctx) headers = { 'X-SMTPAPI': '{"category": "Communication Record %s"}' % ( 'Failure' if error is not None else 'Success') } send_email(message, email_type=settings.CREATE_CONTACT_RECORD, recipients=[to_email], headers=headers)
def send_update_email(self, msg, custom_msg=None): """ This function is meant to be called from the shell. It sends a notice to the user that their saved search has been updated by the system or an admin. Inputs: :msg: The description of the update. Passed through verbatim to the template. Returns: nothing """ context_dict = { 'saved_searches': [(self, )], 'message': msg, 'custom_msg': custom_msg, 'contains_pss': hasattr(self, 'partnersavedsearch') } message = render_to_string("mysearches/email_update.html", context_dict) category = '{"category": "My.jobs Saved Search Updated (%s:%s)"}' % ( self.content_type, self.pk) headers = {'X-SMTPAPI': category} default_reason = 'Jobs are not sent in saved search update emails', log_kwargs = { 'reason': default_reason, 'was_sent': True, 'was_received': False, 'recipient': self.user, 'recipient_email': self.email, 'new_jobs': 0, 'backfill_jobs': 0 } try: send_email(message, email_type=settings.SAVED_SEARCH_UPDATED, recipients=[self.email], label=self.label.strip(), headers=headers) except Exception as e: log_kwargs['was_sent'] = False log_kwargs['reason'] = getattr(e, 'smtp_error', e.message) if context_dict['contains_pss']: reason = log_kwargs['reason'] if reason == default_reason: # Similar to the logic in initial_email, this default reason # serves as a reminder that having zero jobs in this email # is intentional and expected. reason = None self.partnersavedsearch.create_record( "Automatic sending of updated partner saved search.", failure_message=reason) SavedSearchLog.objects.create(**log_kwargs)
def send_disable_email(self): message = render_to_string('mysearches/email_disable.html', {'saved_search': self}) category = '{"category": "My.jobs Saved Search Disabled (%s:%s)"}' % ( self.content_type, self.pk) headers = {'X-SMTPAPI': category} send_email(message, email_type=settings.SAVED_SEARCH_DISABLED, recipients=[self.email], headers=headers)
def send_update_email(self, msg, custom_msg=None): """ This function is meant to be called from the shell. It sends a notice to the user that their saved search has been updated by the system or an admin. Inputs: :msg: The description of the update. Passed through verbatim to the template. Returns: nothing """ context_dict = { 'saved_searches': [(self,)], 'message': msg, 'custom_msg': custom_msg, 'contains_pss': hasattr(self, 'partnersavedsearch') } message = render_to_string("mysearches/email_update.html", context_dict) category = '{"category": "My.jobs Saved Search Updated (%s:%s)"}' % ( self.content_type, self.pk) headers = {'X-SMTPAPI': category} default_reason = 'Jobs are not sent in saved search update emails', log_kwargs = { 'reason': default_reason, 'was_sent': True, 'was_received': False, 'recipient': self.user, 'recipient_email': self.email, 'new_jobs': 0, 'backfill_jobs': 0 } try: send_email(message, email_type=settings.SAVED_SEARCH_UPDATED, recipients=[self.email], label=self.label.strip(), headers=headers) except Exception as e: log_kwargs['was_sent'] = False log_kwargs['reason'] = getattr(e, 'smtp_error', e.message) if context_dict['contains_pss']: reason = log_kwargs['reason'] if reason == default_reason: # Similar to the logic in initial_email, this default reason # serves as a reminder that having zero jobs in this email # is intentional and expected. reason = None self.partnersavedsearch.create_record( "Automatic sending of updated partner saved search.", failure_message=reason ) SavedSearchLog.objects.create(**log_kwargs)
def send_disable_email(self): message = render_to_string('mysearches/email_disable.html', {'saved_search': self}) category = '{"category": "My.jobs Saved Search Disabled (%s:%s)"}' % ( self.content_type, self.pk) headers = {'X-SMTPAPI': category} send_email(message, email_type=settings.SAVED_SEARCH_DISABLED, recipients=[self.email], headers=headers)
def initial_email(self, custom_msg=None, send=True): """ Generates the body for an initial saved search notification and returns it or sends it in an email based on the opt in status of the user. Inputs: :custom_msg: Custom message to be added when manually resending an initial email :send: Denotes if we should send the generated email (True) or return the body (False). If False, the body will be used in an invitation. Default: True Outputs: :message: Generated email body (if :send: is False) or None """ log_kwargs = { 'reason': 'Jobs are not sent in initial saved search emails', 'was_sent': False, 'was_received': False, 'recipient': self.user, 'recipient_email': self.email, 'new_jobs': 0, 'backfill_jobs': 0, 'uuid': uuid.uuid4().hex } message = None if self.user.opt_in_myjobs: # Even if send=False, this will still get sent; send=False currently # means the generated email body will be used in an invitation. log_kwargs['was_sent'] = True context_dict = {'saved_searches': [(self,)], 'custom_msg': custom_msg, 'contains_pss': hasattr(self, 'partnersavedsearch')} message = render_to_string("mysearches/email_initial.html", context_dict) message = Pynliner().from_string(message).run() if send: category = ('{"category": "My.jobs Saved Search Created ' '(%s:%s|%s)"}') % ( self.content_type, self.pk, log_kwargs['uuid']) headers = {'X-SMTPAPI': category} send_email(message, email_type=settings.SAVED_SEARCH_INITIAL, recipients=[self.email], label=self.label.strip(), headers=headers) else: log_kwargs['reason'] = "User can't receive MyJobs email" SavedSearchLog.objects.create(**log_kwargs) if not send: return message
def send_opt_out_notifications(self, saved_searches=None): """ Notify saved search creators that a user has opted out of their emails. """ from mysearches.models import PartnerSavedSearch subject = "My.jobs Partner Saved Search Update" saved_searches = saved_searches or PartnerSavedSearch.objects.filter( user=self) # MySQL doesn't support passing a column to distinct, and I don't want # to deal with dictionaries returned by `values()`, so I just keep # track of unique contacts manually. contacts = [] # need the partner name, so can't send a batch email or message for pss in saved_searches: if (pss.email, pss.partner) in contacts: continue contacts.append((pss.email, pss.partner)) # send notification email message = render_to_string( "mysearches/email_opt_out.html", {'user': self, 'partner': pss.partner, 'company': pss.provider}) headers = { 'X-SMTPAPI': '{"category": "Partner Saved Search Opt Out ' '(%s:%s)"}' % (pss.pk, pss.created_by.pk) } email_type = settings.PARTNER_SAVED_SEARCH_RECIPIENT_OPTED_OUT send_email(message, email_type=email_type, recipients=[pss.created_by.email], headers=headers) # create PRM message body = render_to_string( "mysearches/email_opt_out_message.html", {'user': self, 'partner': pss.partner, 'company': pss.provider}) Message.objects.create_message( subject, body, users=[pss.created_by])
def send_invoice_email(self, send_to_admins=True, other_recipients=None): """ Sends the invoice email to the company admins along with any other optional recipients. Inputs: :send_to_admins: If True will send the invoice to all CompanyUsers of the Company that owns the product. [Defaults to True] :other_recipients: A list object that contains the other recipient(s) email so we can send them the invoice """ from seo.models import CompanyUser other_recipients = [] if not other_recipients else other_recipients data = { 'invoice': self, 'purchases': self.invoiced_products.all(), 'AUTHORIZE_NET': Invoice.AUTHORIZE_NET, 'FREE': Invoice.FREE, 'OFFLINE_PURCHASE': Invoice.OFFLINE_PURCHASE, } owner = self.owner group, _ = Group.objects.get_or_create(name=self.ADMIN_GROUP_NAME) owner_admins = [] if send_to_admins: owner_admins = CompanyUser.objects.filter(company=owner, group=group) owner_admins = owner_admins.values_list('user__email', flat=True) recipients = set(other_recipients + list(owner_admins)) if recipients: body = render_to_string('postajob/invoice_email.html', data) site = getattr(settings, 'SITE', None) headers = { 'X-SMTPAPI': '{"category": "Invoice sent (%s)"}' % self.pk } send_email(body, email_type=settings.INVOICE, recipients=recipients, site=site, headers=headers)
def send_email(self): group, _ = Group.objects.get_or_create(name=self.ADMIN_GROUP_NAME) admin_emails = self.owner.role_set.filter( user__groups=group).values_list('user__email', flat=True) # Confirm that the request object was fully created and still exists # before sending the email. if self.request_object(): data = { 'request': self, 'requester': self.requesting_company().name, } body = render_to_string('postajob/request_email.html', data) site = getattr(settings, 'SITE', None) headers = { 'X-SMTPAPI': '{"category": "Request Created (%s)"}' % self.pk } send_email(body, settings.POSTING_REQUEST_CREATED, recipients=admin_emails, site=site, headers=headers)
def send_contact_record_email_response(created_records, created_contacts, attachment_failures, unmatched_contacts, error, to_email): ctx = { 'created_records': created_records, 'created_contacts': created_contacts, 'error': error, 'unmatched_contacts': unmatched_contacts, 'attachment_failures': attachment_failures, } message = render_to_string('mypartners/email/email_response.html', ctx) headers = { 'X-SMTPAPI': '{"category": "Communication Record %s"}' % ( 'Failure' if error is not None else 'Success') } send_email(message, email_type=settings.CREATE_CONTACT_RECORD, recipients=[to_email], headers=headers)
def send_contact_record_email_response(created_records, created_contacts, attachment_failures, unmatched_contacts, error, to_email, is_nuo=False, company=None, buckets=None): # Multiple outreach email addresses may have been provided. We should have # already ensured that they all belong to one company. Pick one to use in # our return email. bucket = '' if buckets: bucket = buckets[0] ctx = { 'created_records': created_records, 'created_contacts': created_contacts, 'error': error, 'unmatched_contacts': unmatched_contacts, 'attachment_failures': attachment_failures, 'company': company, 'to_email': to_email, 'bucket': bucket, } template = 'mypartners/email/email_response.html' if is_nuo: template = 'mypartners/email/nuo_email_response.html' message = render_to_string(template, ctx) headers = { 'X-SMTPAPI': '{"category": "Communication Record %s"}' % ('Failure' if error is not None else 'Success') } send_email(message, email_type=settings.CREATE_CONTACT_RECORD, recipients=[to_email], headers=headers)
def send_invoice_email(self, send_to_admins=True, other_recipients=None): """ Sends the invoice email to the company admins along with any other optional recipients. Inputs: :send_to_admins: If True will send the invoice to all admin users of the Company that owns the product.[Default: True] :other_recipients: A list object that contains the other recipient(s) email so we can send them the invoice """ other_recipients = other_recipients or [] data = { 'invoice': self, 'purchases': self.invoiced_products.all(), 'AUTHORIZE_NET': Invoice.AUTHORIZE_NET, 'FREE': Invoice.FREE, 'OFFLINE_PURCHASE': Invoice.OFFLINE_PURCHASE, } owner = self.owner group, _ = Group.objects.get_or_create(name=self.ADMIN_GROUP_NAME) owner_admins = owner.role_set.filter(user__groups=group).values_list( 'user__email', flat=True) if send_to_admins else [] recipients = set(other_recipients).union(owner_admins) if recipients: body = render_to_string('postajob/invoice_email.html', data) site = getattr(settings, 'SITE', None) headers = { 'X-SMTPAPI': '{"category": "Invoice sent (%s)"}' % self.pk } send_email(body, email_type=settings.INVOICE, recipients=recipients, site=site, headers=headers)
def send_email(self): group, _ = Group.objects.get_or_create(name=self.ADMIN_GROUP_NAME) admin_emails = self.owner.role_set.filter( user__groups=group).values_list('user__email', flat=True) # Confirm that the request object was fully created and still exists # before sending the email. if self.request_object(): data = { 'request': self, 'requester': self.requesting_company().name, } body = render_to_string('postajob/request_email.html', data) site = getattr(settings, 'SITE', None) headers = { 'X-SMTPAPI': '{"category": "Request Created (%s)"}' % self.pk } send_email(body, settings.POSTING_REQUEST_CREATED, recipients=admin_emails, site=site, headers=headers)
def send_email(self, custom_msg=None): log_kwargs = { 'was_sent': False, 'was_received': False, 'recipient': self.user, 'recipient_email': self.email, 'new_jobs': 0, 'backfill_jobs': 0, 'uuid': uuid.uuid4().hex } total_jobs = 0 saved_searches = self.user.savedsearch_set.filter(is_active=True) search_list = [] contains_pss = False for search in saved_searches: items, count = search.get_feed_items() total_jobs += count pss = None if hasattr(search, 'partnersavedsearch'): pss = search.partnersavedsearch elif isinstance(search, PartnerSavedSearch): pss = search if pss is not None: # New jobs will have a "new" key in their job dictionaries. # We can count the number that do not log_kwargs['backfill_jobs'] += len([item for item in items if not item.get('new')]) log_kwargs['new_jobs'] += count - log_kwargs['backfill_jobs'] contains_pss = True extras = pss.url_extras if extras: mypartners.helpers.add_extra_params_to_jobs(items, extras) search.url = mypartners.helpers.add_extra_params(search.url, extras) pss.create_record(custom_msg) search_list.append((search, items, count)) saved_searches = [(search, items, count) for search, items, count in search_list if (items or hasattr(search, 'partnersavedsearch'))] if self.user.can_receive_myjobs_email() and saved_searches: log_kwargs['was_sent'] = True context_dict = { 'saved_searches': saved_searches, 'digest': self, 'custom_msg': custom_msg, 'contains_pss': contains_pss } message = render_to_string('mysearches/email_digest.html', context_dict) category = '{"category": "My.jobs Saved Search Digest Send (%s:%s:%s:%s)"}' % ( self.content_type, self.pk, ','.join([str(search[0].pk) for search in saved_searches]), log_kwargs['uuid']) headers = {'X-SMTPAPI': category} send_email(message, email_type=settings.SAVED_SEARCH_DIGEST, recipients=[self.email], headers=headers) sent_search_kwargs = { 'pk__in': [search[0].pk for search in saved_searches] } searches_sent = SavedSearch.objects.filter(**sent_search_kwargs) searches_sent.update(last_sent=datetime.now()) else: if not saved_searches: log_kwargs['reason'] = ("No saved searches or saved searches " "have no jobs") else: log_kwargs['reason'] = "User can't receive MyJobs email" SavedSearchLog.objects.create(**log_kwargs)
def initial_email(self, custom_msg=None, send=True): """ Generates the body for an initial saved search notification and returns it or sends it in an email based on the opt in status of the user. Inputs: :custom_msg: Custom message to be added when manually resending an initial email :send: Denotes if we should send the generated email (True) or return the body (False). If False, the body will be used in an invitation. Default: True Outputs: :message: Generated email body (if :send: is False) or None """ default_reason = 'Jobs are not sent in initial saved search emails' log_kwargs = { 'reason': default_reason, 'was_sent': False, 'was_received': False, 'recipient': self.user, 'recipient_email': self.email, 'new_jobs': 0, 'backfill_jobs': 0, 'uuid': uuid.uuid4().hex } message = None if self.user.opt_in_myjobs: # Even if send=False, this will still get sent; send=False currently # means the generated email body will be used in an invitation. log_kwargs['was_sent'] = True context_dict = {'saved_searches': [(self,)], 'custom_msg': custom_msg, 'contains_pss': hasattr(self, 'partnersavedsearch')} message = render_to_string("mysearches/email_initial.html", context_dict) message = Pynliner().from_string(message).run() if send: category = ('{"category": "My.jobs Saved Search Created ' '(%s:%s|%s)"}') % ( self.content_type, self.pk, log_kwargs['uuid']) headers = {'X-SMTPAPI': category} try: send_email(message, email_type=settings.SAVED_SEARCH_INITIAL, recipients=[self.email], label=self.label.strip(), headers=headers) except Exception as e: log_kwargs['was_sent'] = False log_kwargs['reason'] = getattr(e, 'smtp_error', e.message) if context_dict['contains_pss']: reason = log_kwargs['reason'] if reason == default_reason: # Most other instances of SavedSearchLog have nothing # in the reason field when successful. This one is a # little different, serving as a reminder of why this # particular email contains no jobs. reason = None self.partnersavedsearch.create_record( "Automatic sending of initial partner saved search", failure_message=reason ) else: log_kwargs['reason'] = "User can't receive MyJobs email" SavedSearchLog.objects.create(**log_kwargs) if not send: return message
def send_email(self, custom_msg=None): log_kwargs = { 'was_sent': False, 'was_received': False, 'recipient': self.user, 'recipient_email': self.email, 'new_jobs': 0, 'backfill_jobs': 0, 'uuid': uuid.uuid4().hex } total_jobs = 0 saved_searches = self.user.savedsearch_set.filter(is_active=True) search_list = [] needs_records = [] contains_pss = False for search in saved_searches: items, count = search.get_feed_items() total_jobs += count pss = None if hasattr(search, 'partnersavedsearch'): pss = search.partnersavedsearch elif isinstance(search, PartnerSavedSearch): pss = search if pss is not None: # We know partner searches require communication records but # we need to put off the creation of them until we find out # if said communication was successful. needs_records.append(pss) # New jobs will have a "new" key in their job dictionaries. # We can count the number that do not log_kwargs['backfill_jobs'] += len( [item for item in items if not item.get('new')]) log_kwargs['new_jobs'] += count - log_kwargs['backfill_jobs'] contains_pss = True extras = pss.url_extras if extras: mypartners.helpers.add_extra_params_to_jobs(items, extras) search.url = mypartners.helpers.add_extra_params( search.url, extras) search_list.append((search, items, count)) saved_searches = [(search, items, count) for search, items, count in search_list if (items or hasattr(search, 'partnersavedsearch'))] if self.user.can_receive_myjobs_email() and saved_searches: log_kwargs['was_sent'] = True context_dict = { 'saved_searches': saved_searches, 'digest': self, 'custom_msg': custom_msg, 'contains_pss': contains_pss } message = render_to_string('mysearches/email_digest.html', context_dict) category = '{"category": "My.jobs Saved Search Digest Send (%s:%s:%s:%s)"}' % ( self.content_type, self.pk, ','.join( [str(search[0].pk) for search in saved_searches]), log_kwargs['uuid']) headers = {'X-SMTPAPI': category} try: send_email(message, email_type=settings.SAVED_SEARCH_DIGEST, recipients=[self.email], headers=headers) except Exception as e: log_kwargs['was_sent'] = False log_kwargs['reason'] = getattr(e, 'smtp_error', e.message) else: sent_search_kwargs = { 'pk__in': [search[0].pk for search in saved_searches] } searches_sent = SavedSearch.objects.filter( **sent_search_kwargs) searches_sent.update(last_sent=datetime.now()) else: if not saved_searches: log_kwargs['reason'] = ("No saved searches or saved searches " "have no jobs") else: log_kwargs['reason'] = "User can't receive MyJobs email" for pss in needs_records: pss.create_record(custom_msg, failure_message=log_kwargs.get('reason')) SavedSearchLog.objects.create(**log_kwargs)
def send_email(self, custom_msg=None, additional_categories=None, additional_headers=None): log_kwargs = { 'was_sent': False, 'was_received': False, 'recipient': self.user, 'recipient_email': self.email, 'new_jobs': 0, 'backfill_jobs': 0, 'uuid': uuid.uuid4().hex } if self.user.can_receive_myjobs_email(): items, count = self.get_feed_items() is_pss = hasattr(self, 'partnersavedsearch') if items or is_pss: log_kwargs['was_sent'] = True if is_pss: extras = self.partnersavedsearch.url_extras if extras: mypartners.helpers.add_extra_params_to_jobs(items, extras) self.url = mypartners.helpers.add_extra_params(self.url, extras) if self.custom_message and not custom_msg: custom_msg = self.custom_message context_dict = {'saved_searches': [(self, items, count)], 'custom_msg': custom_msg, 'contains_pss': is_pss} message = render_to_string('mysearches/email_single.html', context_dict) categories = [('My.jobs Saved Search Sent ' '({content_type}:{pk}|{uuid})').format( content_type=self.content_type, pk=self.pk, uuid=log_kwargs['uuid']), settings.ENVIRONMENT] # additional_categories and additional_headers are used when # sending email from qc/staging to stop SendGrid's url # redirection and to enable us to drop events that we shouldn't # be processing (QC emails getting posted to Production) if additional_categories is not None: categories.extend( additional_categories if isinstance( additional_categories, list) else [additional_categories]) categories = ['"%s"' % category for category in categories] category = '[%s]' % ','.join(categories) header = ['"category": ' + category] if additional_headers is not None: header.extend( additional_headers if isinstance( additional_headers, list) else [additional_headers]) header = '{%s}' % (','.join(header), ) headers = {'X-SMTPAPI': header} send_email(message, email_type=settings.SAVED_SEARCH, recipients=[self.email], label=self.label.strip(), headers=headers) self.last_sent = datetime.now() self.save() if is_pss: record = self.partnersavedsearch.create_record(custom_msg) log_kwargs['contact_record'] = record log_kwargs['new_jobs'] = len([item for item in items if item.get('new')]) log_kwargs['backfill_jobs'] = count - log_kwargs['new_jobs'] else: log_kwargs['new_jobs'] = count log_kwargs['backfill_jobs'] = 0 else: log_kwargs['reason'] = 'No jobs' else: log_kwargs['reason'] = "User can't receive MyJobs email" SavedSearchLog.objects.create(**log_kwargs)
def initial_email(self, custom_msg=None, send=True): """ Generates the body for an initial saved search notification and returns it or sends it in an email based on the opt in status of the user. Inputs: :custom_msg: Custom message to be added when manually resending an initial email :send: Denotes if we should send the generated email (True) or return the body (False). If False, the body will be used in an invitation. Default: True Outputs: :message: Generated email body (if :send: is False) or None """ default_reason = 'Jobs are not sent in initial saved search emails' log_kwargs = { 'reason': default_reason, 'was_sent': False, 'was_received': False, 'recipient': self.user, 'recipient_email': self.email, 'new_jobs': 0, 'backfill_jobs': 0, 'uuid': uuid.uuid4().hex } message = None if self.user.opt_in_myjobs: # Even if send=False, this will still get sent; send=False currently # means the generated email body will be used in an invitation. log_kwargs['was_sent'] = True context_dict = { 'saved_searches': [(self, )], 'custom_msg': custom_msg, 'contains_pss': hasattr(self, 'partnersavedsearch') } message = render_to_string("mysearches/email_initial.html", context_dict) message = Pynliner().from_string(message).run() if send: category = ('{"category": "My.jobs Saved Search Created ' '(%s:%s|%s)"}') % (self.content_type, self.pk, log_kwargs['uuid']) headers = {'X-SMTPAPI': category} try: send_email(message, email_type=settings.SAVED_SEARCH_INITIAL, recipients=[self.email], label=self.label.strip(), headers=headers) except Exception as e: log_kwargs['was_sent'] = False log_kwargs['reason'] = getattr(e, 'smtp_error', e.message) if context_dict['contains_pss']: reason = log_kwargs['reason'] if reason == default_reason: # Most other instances of SavedSearchLog have nothing # in the reason field when successful. This one is a # little different, serving as a reminder of why this # particular email contains no jobs. reason = None self.partnersavedsearch.create_record( "Automatic sending of initial partner saved search", failure_message=reason) else: log_kwargs['reason'] = "User can't receive MyJobs email" SavedSearchLog.objects.create(**log_kwargs) if not send: return message
def send_email(self, custom_msg=None, additional_categories=None, additional_headers=None): log_kwargs = { 'was_sent': False, 'was_received': False, 'recipient': self.user, 'recipient_email': self.email, 'new_jobs': 0, 'backfill_jobs': 0, 'uuid': uuid.uuid4().hex } if self.user.can_receive_myjobs_email(): items, count = self.get_feed_items() is_pss = hasattr(self, 'partnersavedsearch') if items or is_pss: log_kwargs['was_sent'] = True if is_pss: extras = self.partnersavedsearch.url_extras if extras: mypartners.helpers.add_extra_params_to_jobs( items, extras) self.url = mypartners.helpers.add_extra_params( self.url, extras) if self.custom_message and not custom_msg: custom_msg = self.custom_message context_dict = { 'saved_searches': [(self, items, count)], 'custom_msg': custom_msg, 'contains_pss': is_pss } message = render_to_string('mysearches/email_single.html', context_dict) categories = [('My.jobs Saved Search Sent ' '({content_type}:{pk}|{uuid})').format( content_type=self.content_type, pk=self.pk, uuid=log_kwargs['uuid']), settings.ENVIRONMENT] # additional_categories and additional_headers are used when # sending email from qc/staging to stop SendGrid's url # redirection and to enable us to drop events that we shouldn't # be processing (QC emails getting posted to Production) if additional_categories is not None: categories.extend(additional_categories if isinstance( additional_categories, list ) else [additional_categories]) categories = ['"%s"' % category for category in categories] category = '[%s]' % ','.join(categories) header = ['"category": ' + category] if additional_headers is not None: header.extend(additional_headers if isinstance( additional_headers, list) else [additional_headers]) header = '{%s}' % (','.join(header), ) headers = {'X-SMTPAPI': header} try: send_email(message, email_type=settings.SAVED_SEARCH, recipients=[self.email], label=self.label.strip(), headers=headers, text_only=self.text_only) except Exception as e: log_kwargs['was_sent'] = False log_kwargs['reason'] = getattr(e, 'smtp_error', e.message) else: self.last_sent = datetime.now() self.save() if is_pss: record = self.partnersavedsearch.create_record( custom_msg, failure_message=log_kwargs.get('reason')) log_kwargs['contact_record'] = record log_kwargs['new_jobs'] = len( [item for item in items if item.get('new')]) log_kwargs['backfill_jobs'] = count - \ log_kwargs['new_jobs'] else: log_kwargs['new_jobs'] = count log_kwargs['backfill_jobs'] = 0 else: log_kwargs['reason'] = 'No jobs' else: log_kwargs['reason'] = "User can't receive MyJobs email" SavedSearchLog.objects.create(**log_kwargs)
def email_user(self, message, email_type=settings.GENERIC, **kwargs): headers = kwargs.pop('headers', {}) if 'X-SMTPAPI' not in headers: headers['X-SMTPAPI'] = '{"category": "Email to User (%s)"}' % self.pk send_email(message, email_type=email_type, recipients=[self.email], headers=headers, **kwargs)