def handle(self, *args, **options): plaintext = get_template('email/weekly.txt') htmly = get_template('email/weekly.html') all_users = User.objects.exclude(extra__emails=False) for user in all_users: # start by finding the ideas posted by a user commented_on_ideas = user.get_profile().comments_on_owned_ideas(7) self.stdout.write("user %s\n" %user) for idea in commented_on_ideas: self.stdout.write("you've got new comments on: %s\n" % idea.idea) #new_slates = user.slates.all() new_slates = user.slates.filter( date_created__gte = datetime.date.today()-datetime.timedelta(7) ) self.stdout.write("you've joined %i slates \n" % len(new_slates)) d = Context({ 'user': user }) #actually send the e-mail if new_slates and commented_on_ideas: subject, from_email, to = 'Weekly Digest', '*****@*****.**', user.email text_content = plaintext.render(d) html_content = htmly.render(d) msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") if "final" in args: try: msg.send() except: self.stdout.write("failed to send email") else: self.stdout.write("test success")
def email_everyone(request, *args, **kwargs): if request.method == 'POST': subject = request.POST.get('subject', '') message = request.POST.get('message', '') t = get_template('contact/email.html') c = Context({'message': message}) html_content = t.render(c) text_content = strip_tags(html_content) for profile in Profile.objects.all(): msg = EmailMultiAlternatives(subject, text_content, '*****@*****.**', [profile.user.email]) msg.attach_alternative(html_content, "text/html") msg.send() return redirect("/") else: form = EmailForm() return render_to_response('contact/email_everyone.html', { 'form': form, }, RequestContext(request))
def confirm_cart_to_user(profile, action): """send message by email""" from_email = getattr(settings, 'DEFAULT_FROM_EMAIL') subject = get_cart_confirmation_subject() data = { 'profile': profile, 'action': action, 'subject': subject, } the_template = get_template('Store/cart_confirmation_email.html') html_text = the_template.render(Context(data)) text = dehtml(html_text) email = EmailMultiAlternatives( subject, text, from_email, [profile.contact.email], ) email.attach_alternative(html_text, "text/html") try: email.send() except Exception: logger.exception("confirm_cart_to_user")
def send_email(request): if request.method == 'POST': try: from django.core.mail import EmailMultiAlternatives behalf = request.POST['behalf'] to = request.POST['to'] cc = request.POST['cc'] bcc = request.POST['bcc'] subject = request.POST['subject'] body = request.POST['body'] if hasattr(settings, 'REPLY_TO'): reply_to = {'Reply-To': settings.REPLY_TO, 'Return-Path': settings.REPLY_TO} else: reply_to = {} e = EmailMultiAlternatives( subject=subject, from_email=behalf, to=to.split(';'), cc=cc.split(';'), bcc=bcc.split(';'), headers=reply_to ) e.attach_alternative(body, 'text/html') e.content_subtype = 'html' e.send() return HttpResponse(dumps({'status': 'ok'}), content_type="application/json") except Exception, e: return HttpResponse(dumps({'status': 'ko', 'error': str(e)}), content_type="application/json")
def send_activation_email( user=None, request=None, from_email=None, subject_template='users/activation_email_subject.html', email_template='users/activation_email.html', html_email_template=None): if not user.is_active and settings.USERS_VERIFY_EMAIL: token_generator = EmailActivationTokenGenerator() current_site = get_current_site(request) context = { 'email': user.email, 'site': current_site, 'expiration_days': settings.USERS_EMAIL_CONFIRMATION_TIMEOUT_DAYS, 'user': user, 'uid': urlsafe_base64_encode(force_bytes(user.pk)), 'token': token_generator.make_token(user=user), 'protocol': 'https' if request.is_secure() else 'http', } subject = render_to_string(subject_template, context) # email subject *must not* contain newlines subject = ''.join(subject.splitlines()) body = render_to_string(email_template, context) email_message = EmailMultiAlternatives(subject, body, from_email, [user.email]) if html_email_template is not None: html_email = render_to_string(html_email_template, context) email_message.attach_alternative(html_email, 'text/html') email_message.send()
def send_premium_expire_email(self, force=False): if not self.user.email: logging.user(self.user, "~FM~SB~FRNot~FM sending premium expire for user: %s" % (self.user)) return emails_sent = MSentEmail.objects.filter(receiver_user_id=self.user.pk, email_type='premium_expire') day_ago = datetime.datetime.now() - datetime.timedelta(days=360) for email in emails_sent: if email.date_sent > day_ago: logging.user(self.user, "~FM~SBNot sending premium expire email, already sent before.") return delta = datetime.datetime.now() - self.last_seen_on months_ago = delta.days / 30 user = self.user data = dict(user=user, months_ago=months_ago) text = render_to_string('mail/email_premium_expire.txt', data) html = render_to_string('mail/email_premium_expire.xhtml', data) subject = "Your premium account on NewsBlur has expired" msg = EmailMultiAlternatives(subject, text, from_email='NewsBlur <%s>' % settings.HELLO_EMAIL, to=['%s <%s>' % (user, user.email)]) msg.attach_alternative(html, "text/html") msg.send(fail_silently=True) MSentEmail.record(receiver_user_id=self.user.pk, email_type='premium_expire') logging.user(self.user, "~BB~FM~SBSending premium expire email for user: %s months, %s" % (months_ago, self.user.email))
def notify_cart_to_admin(profile, action): """send message by email""" notification_email = getattr(settings, 'BALAFON_NOTIFICATION_EMAIL', '') if notification_email: from_email = getattr(settings, 'DEFAULT_FROM_EMAIL') subject = _(u"New cart purchased on store") data = { 'profile': profile, 'action': action, 'subject': subject, } the_template = get_template('Store/cart_notification_email.html') html_text = the_template.render(Context(data)) text = dehtml(html_text) email = EmailMultiAlternatives( subject, text, from_email, [notification_email], headers={'Reply-To': profile.contact.email} ) email.attach_alternative(html_text, "text/html") try: email.send() except Exception: logger.exception("notify_cart_to_admin")
def send_new_premium_email(self, force=False): subs = UserSubscription.objects.filter(user=self.user) message = """Woohoo! User: %(user)s Feeds: %(feeds)s Sincerely, NewsBlur""" % {'user': self.user.username, 'feeds': subs.count()} mail_admins('New premium account', message, fail_silently=True) if not self.user.email or not self.send_emails: return sent_email, created = MSentEmail.objects.get_or_create(receiver_user_id=self.user.pk, email_type='new_premium') if not created and not force: return user = self.user text = render_to_string('mail/email_new_premium.txt', locals()) html = render_to_string('mail/email_new_premium.xhtml', locals()) subject = "Thanks for going premium on NewsBlur!" msg = EmailMultiAlternatives(subject, text, from_email='NewsBlur <%s>' % settings.HELLO_EMAIL, to=['%s <%s>' % (user, user.email)]) msg.attach_alternative(html, "text/html") msg.send(fail_silently=True) logging.user(self.user, "~BB~FM~SBSending email for new premium: %s" % self.user.email)
def send_launch_social_email(self, force=False): if not self.user.email or not self.send_emails: logging.user(self.user, "~FM~SB~FRNot~FM sending launch social email for user, %s: %s" % (self.user.email and 'opt-out: ' or 'blank', self.user.email)) return sent_email, created = MSentEmail.objects.get_or_create(receiver_user_id=self.user.pk, email_type='launch_social') if not created and not force: logging.user(self.user, "~FM~SB~FRNot~FM sending launch social email for user, sent already: %s" % self.user.email) return delta = datetime.datetime.now() - self.last_seen_on months_ago = delta.days / 30 user = self.user data = dict(user=user, months_ago=months_ago) text = render_to_string('mail/email_launch_social.txt', data) html = render_to_string('mail/email_launch_social.xhtml', data) subject = "NewsBlur is now a social news reader" msg = EmailMultiAlternatives(subject, text, from_email='NewsBlur <%s>' % settings.HELLO_EMAIL, to=['%s <%s>' % (user, user.email)]) msg.attach_alternative(html, "text/html") msg.send(fail_silently=True) logging.user(self.user, "~BB~FM~SBSending launch social email for user: %s months, %s" % (months_ago, self.user.email))
def send_opml_export_email(self): if not self.user.email: return MSentEmail.objects.get_or_create(receiver_user_id=self.user.pk, email_type='opml_export') exporter = OPMLExporter(self.user) opml = exporter.process() params = { 'feed_count': UserSubscription.objects.filter(user=self.user).count(), } user = self.user text = render_to_string('mail/email_opml_export.txt', params) html = render_to_string('mail/email_opml_export.xhtml', params) subject = "Backup OPML file of your NewsBlur sites" filename= 'NewsBlur Subscriptions - %s.xml' % datetime.datetime.now().strftime('%Y-%m-%d') msg = EmailMultiAlternatives(subject, text, from_email='NewsBlur <%s>' % settings.HELLO_EMAIL, to=['%s <%s>' % (user, user.email)]) msg.attach_alternative(html, "text/html") msg.attach(filename, opml, 'text/xml') msg.send(fail_silently=True) logging.user(self.user, "~BB~FM~SBSending OPML backup email to: %s" % self.user.email)
def send_first_share_to_blurblog_email(self, force=False): from apps.social.models import MSocialProfile, MSharedStory if not self.user.email: return sent_email, created = MSentEmail.objects.get_or_create(receiver_user_id=self.user.pk, email_type='first_share') if not created and not force: return social_profile = MSocialProfile.objects.get(user_id=self.user.pk) params = { 'shared_stories': MSharedStory.objects.filter(user_id=self.user.pk).count(), 'blurblog_url': social_profile.blurblog_url, 'blurblog_rss': social_profile.blurblog_rss } user = self.user text = render_to_string('mail/email_first_share_to_blurblog.txt', params) html = render_to_string('mail/email_first_share_to_blurblog.xhtml', params) subject = "Your shared stories on NewsBlur are available on your Blurblog" msg = EmailMultiAlternatives(subject, text, from_email='NewsBlur <%s>' % settings.HELLO_EMAIL, to=['%s <%s>' % (user, user.email)]) msg.attach_alternative(html, "text/html") msg.send(fail_silently=True) logging.user(self.user, "~BB~FM~SBSending first share to blurblog email to: %s" % self.user.email)
def email_about_suggested_event_comment(comment, base_url): base_url = fix_base_url(base_url) emails = _get_add_event_emails() event_title = comment.suggested_event.title if len(event_title) > 30: event_title = '%s...' % event_title[:27] subject = ( '[Air Mozilla] New comment on suggested event: %s' % event_title ) context = { 'event': comment.suggested_event, 'comment': comment, 'base_url': base_url, 'subject': subject, } html_body = render_to_string( 'suggest/_email_comment.html', context ) assert emails body = html2text(html_body) email = EmailMultiAlternatives( subject, body, settings.EMAIL_FROM_ADDRESS, emails ) email.attach_alternative(html_body, "text/html") email.send()
def email_about_suggested_event(event, base_url): base_url = fix_base_url(base_url) emails = _get_add_event_emails() event_title = event.title if len(event_title) > 30: event_title = '%s...' % event_title[:27] comments = ( SuggestedEventComment.objects .filter(suggested_event=event) .order_by('created') ) subject = ( '[Air Mozilla] New suggested event: %s' % event_title ) assert emails context = { 'event': event, 'base_url': base_url, 'comments': comments, 'subject': subject, } html_body = render_to_string( 'suggest/_email_submitted.html', context ) body = html2text(html_body) email = EmailMultiAlternatives( subject, body, settings.EMAIL_FROM_ADDRESS, emails ) email.attach_alternative(html_body, "text/html") email.send()
def send_html_mail( subject, message, message_html, from_email, recipient_list, priority="medium", fail_silently=False, auth_user=None, auth_password=None, ): """ Function to queue HTML e-mails """ from django.utils.encoding import force_unicode from django.core.mail import EmailMultiAlternatives from mailer.models import make_message priority = PRIORITY_MAPPING[priority] # need to do this in case subject used lazy version of ugettext subject = force_unicode(subject) message = force_unicode(message) msg = make_message(subject=subject, body=message, from_email=from_email, to=recipient_list, priority=priority) email = msg.email email = EmailMultiAlternatives(email.subject, email.body, email.from_email, email.to) email.attach_alternative(message_html, "text/html") msg.email = email msg.save() return 1
def test_encoding(self): """ Regression for #12791 - Encode body correctly with other encodings than utf-8 """ email = EmailMessage('Subject', 'Firstname Sürname is a great guy.', '*****@*****.**', ['*****@*****.**']) email.encoding = 'iso-8859-1' message = email.message() self.assertMessageHasHeaders(message, { ('MIME-Version', '1.0'), ('Content-Type', 'text/plain; charset="iso-8859-1"'), ('Content-Transfer-Encoding', 'quoted-printable'), ('Subject', 'Subject'), ('From', '*****@*****.**'), ('To', '*****@*****.**')}) self.assertEqual(message.get_payload(), 'Firstname S=FCrname is a great guy.') # Make sure MIME attachments also works correctly with other encodings than utf-8 text_content = 'Firstname Sürname is a great guy.' html_content = '<p>Firstname Sürname is a <strong>great</strong> guy.</p>' msg = EmailMultiAlternatives('Subject', text_content, '*****@*****.**', ['*****@*****.**']) msg.encoding = 'iso-8859-1' msg.attach_alternative(html_content, "text/html") payload0 = msg.message().get_payload(0) self.assertMessageHasHeaders(payload0, { ('MIME-Version', '1.0'), ('Content-Type', 'text/plain; charset="iso-8859-1"'), ('Content-Transfer-Encoding', 'quoted-printable')}) self.assertTrue(payload0.as_bytes().endswith(b'\n\nFirstname S=FCrname is a great guy.')) payload1 = msg.message().get_payload(1) self.assertMessageHasHeaders(payload1, { ('MIME-Version', '1.0'), ('Content-Type', 'text/html; charset="iso-8859-1"'), ('Content-Transfer-Encoding', 'quoted-printable')}) self.assertTrue(payload1.as_bytes().endswith(b'\n\n<p>Firstname S=FCrname is a <strong>great</strong> guy.</p>'))
def sendMailToContacts(name, html, text): # Get a list of all of the current contactees contacts = ContactEmail.objects.all() email_addresses = [] # Build E-Mail subject = str(name) + " has requested a Quote on SCCS" text_message = text html_message = html from_addr = "*****@*****.**" # Create List of e-mail addresses for address in contacts: email_addresses.append(address.email) try: # Get django e-mail settings connection = mail.get_connection() # Open E-Mail server connection connection.open() # Append RAW Text email_message = EmailMultiAlternatives(subject, text_message, from_addr, email_addresses, connection=connection) # Append HTML email_message.attach_alternative(html_message, "text/html") # Send Message email_message.send() connection.close() except Exception as err: connection.close() log(err)
def send_forgot_password_email(self): self.forgot_password_token = self._generate_token() self.save() try: to = self.user.email from_email = settings.DEFAULT_FROM_EMAIL subject = settings.DEFAULT_EMAIL_FORGOT_PASSWORD_SUBJECT forgot_password_link = "%s/user/reset-password/token/%s/" % (settings.BASE_URL, self.forgot_password_token) body = u"Dear {name},".format(name=self.user.first_name) body += u"To update your password access link below:" body += u"{link}".format(link=forgot_password_link) body += u"Graciously," body += u"Dashboard Team." body_html = u"Dear %s,<br /><br />".format(name=self.user.first_name) body_html += u"To update your password access link below:<br /><br />" body_html += u"<a href='{link}'>{link}</a><br /><br />".format(link=forgot_password_link) body_html += u"Graciously,<br />" body_html += u"Dashboard Team." msg = EmailMultiAlternatives(subject, body, from_email, [to]) msg.attach_alternative(body_html, "text/html") msg.send() return True except Exception: logging.error("[FORGOT PASSWORD] - sending email failure.") return False
def send_customer_added(user): """Sends a mail to a newly registered user. """ import muecke.core.utils shop = muecke.core.utils.get_default_shop() subject = _(u"Welcome to %s" % shop.name) from_email = shop.from_email to = [user.username] bcc = shop.get_notification_emails() # text text = render_to_string("muecke/mail/new_user_mail.txt", { "user": user, "shop": shop}) # subject subject = render_to_string("muecke/mail/new_user_mail_subject.txt", { "user": user, "shop": shop}) mail = EmailMultiAlternatives( subject=subject, body=text, from_email=from_email, to=to, bcc=bcc) # html html = render_to_string("muecke/mail/new_user_mail.html", { "user": user, "shop": shop, }) mail.attach_alternative(html, "text/html") mail.send(fail_silently=True)
def maid_profile(request, pk): """ Home Page """ success_msg = None try: maids = Maid.objects.get(pk=pk) except Maid.DoesNotExist: maids = None if request.method == 'POST': from django.core.mail import EmailMultiAlternatives from django.template.loader import render_to_string from django.utils.html import strip_tags subject = 'Share maid details' html_content = render_to_string('templated_email/share_friend.html', {'maids':maids, 'DOMAIN_URL': settings.DOMAIN_URL,}) # ... text_content = strip_tags(html_content) # this strips the html, so people will have the text as well. # create the email, and attach the HTML version as well. msg = EmailMultiAlternatives(subject, text_content, '*****@*****.**', [request.POST.get('email')]) msg.attach_alternative(html_content, "text/html") msg.send() success_msg = "Your request successfully sent to your Friend." return render_to_response('maid_profiile.html',{'maids':maids, 'success_msg':success_msg}, context_instance=RequestContext(request))
def send_review_added(review): """Sends a mail to shop admins that a new review has been added """ import muecke.core.utils shop = muecke.core.utils.get_default_shop() subject = _(u"New review has been added") from_email = shop.from_email to = shop.get_notification_emails() ctype = ContentType.objects.get_for_id(review.content_type_id) product = ctype.get_object_for_this_type(pk=review.content_id) # text text = render_to_string("muecke/mail/review_added_mail.txt", { "review": review, "product": product, }) mail = EmailMultiAlternatives( subject=subject, body=text, from_email=from_email, to=to) # html html = render_to_string("muecke/mail/review_added_mail.html", { "site": "http://%s" % Site.objects.get(id=settings.SITE_ID), "review": review, "product": product, }) mail.attach_alternative(html, "text/html") mail.send(fail_silently=True)
def send_order_received_mail(order): """Sends an order received mail to the shop customer. Customer information is taken from the provided order. """ import muecke.core.utils shop = muecke.core.utils.get_default_shop() try: subject = render_to_string("muecke/mail/order_received_subject.txt", {"order": order}) except TemplateDoesNotExist: subject = _(u"Your order has been received") from_email = shop.from_email to = [order.customer_email] bcc = shop.get_notification_emails() # text text = render_to_string("muecke/mail/order_received_mail.txt", {"order": order}) mail = EmailMultiAlternatives( subject=subject, body=text, from_email=from_email, to=to, bcc=bcc) # html html = render_to_string("muecke/mail/order_received_mail.html", { "order": order }) mail.attach_alternative(html, "text/html") mail.send(fail_silently=True)
def send_warning_email(date=None, url=None, addr=None, job_name=None): """ Args: date: A datetime object representing when the run will expire url: The url to the detail page of the export addr: The email address to which the email will be sent Returns: None """ subject = "Your EventKit DataPack is set to expire." to = [addr] from_email = getattr( settings, 'DEFAULT_FROM_EMAIL', 'Eventkit Team <*****@*****.**>' ) ctx = {'url': url, 'date': str(date), 'job_name': job_name} text = get_template('email/expiration_warning.txt').render(ctx) html = get_template('email/expiration_warning.html').render(ctx) try: msg = EmailMultiAlternatives(subject, text, to=to, from_email=from_email) msg.attach_alternative(html, "text/html") msg.send() except Exception as e: logger.error("Encountered an error when sending status email: {}".format(e))
def send_activation_email(request, user): username = user.username email = user.email salt = hashlib.sha1(str(random.random())).hexdigest()[:5] activation_key = hashlib.sha1(salt + email).hexdigest() # Create and save user profile new_profile = UserProfile(user=user, activation_key=activation_key) new_profile.save() # Send email with activation key activation_link = request.META['HTTP_HOST'] + \ reverse('users:confirm', kwargs={'activation_key': activation_key}) email_subject = 'Account confirmation' email_body = render_to_string('index/activation_email.html', {'username': username, 'activation_link': activation_link, 'active_time': new_profile.active_time}) msg = EmailMultiAlternatives(email_subject, email_body, EMAIL_HOST_USER, [email]) msg.attach_alternative(email_body, "text/html") try: Thread(target=msg.send, args=()).start() except: logger.warning("There is an error when sending email to %s's mailbox" % username)
def send_to(self, to): """ Send email """ if settings.DEVELOPMENT: print "[MAGICEMAIL][DEVELOPMENT] Skipping send email: {0} >>>".format( self._subject.encode('utf-8')) return True self._to = to if not self._reply_to: self._reply_to = self._from email_headers = {'h:Reply-To': self._reply_to, 'Reply-To': self._reply_to, } if self._extra_data: email_headers['v:my-custom-data'] = self._extra_data email = EmailMultiAlternatives( subject=self._subject, body=self._data.get('body'), from_email=self._from, to=self._to, headers=email_headers ) email.attach_alternative(self._template_content(), "text/html") if self._extra_data: email.extra_headers['X-Mailgun-Variables'] = email_headers email.send() return True
def render_mail(self, template_prefix, email, context): """ Renders an e-mail to `email`. `template_prefix` identifies the e-mail that is to be sent, e.g. "account/email/email_confirmation" """ subject = render_to_string('{0}_subject.txt'.format(template_prefix), context) # remove superfluous line breaks subject = " ".join(subject.splitlines()).strip() subject = self.format_email_subject(subject) bodies = {} for ext in ['html', 'txt']: try: template_name = '{0}_message.{1}'.format(template_prefix, ext) bodies[ext] = render_to_string(template_name, context).strip() except TemplateDoesNotExist: if ext == 'txt' and not bodies: # We need at least one body raise if 'txt' in bodies: msg = EmailMultiAlternatives(subject, bodies['txt'], settings.DEFAULT_FROM_EMAIL, [email]) if 'html' in bodies: msg.attach_alternative(bodies['html'], 'text/html') else: msg = EmailMessage(subject, bodies['html'], settings.DEFAULT_FROM_EMAIL, [email]) msg.content_subtype = 'html' # Main content is now text/html return msg
def enviar_mail_activacion(usuario): # Se genera token con email del usuario. token_link = generar_token(usuario.email, url=True) token_clave = generar_token(usuario.id) # Creación de URL de confirmación confirm_url = FRONTEND_URL + 'activar-cuenta/' + token_link # Obtención de templates html y txt de emails. htmly = loader.get_template('emails/html/confirmar_cuenta.html') text = loader.get_template('emails/txt/confirmar_cuenta.txt') # Definición de variables de contexto variables = { 'usuario': usuario, 'confirm_url': confirm_url, 'clave': token_clave } html_content = htmly.render(variables) text_content = text.render(variables) # Creación y envío de email. msg = EmailMultiAlternatives( 'Bienvenido a Manos por gotas', text_content, to=[usuario.email] ) msg.attach_alternative(html_content, "text/html") msg.send()
def enviar_mail_reiniciar_password(usuario): # Se genera token con email del usuario. token_link = generar_token(usuario.email, url=True) # Creación de URL de confirmación reset_url = FRONTEND_URL + 'reset-password/' + token_link # Obtención de templates html y txt de emails. htmly = loader.get_template('emails/html/reiniciar_password.html') text = loader.get_template('emails/txt/reiniciar_password.txt') # Definición de variables de contexto variables = { 'usuario': usuario, 'reset_url': reset_url, } html_content = htmly.render(variables) text_content = text.render(variables) # Creación y envío de email. msg = EmailMultiAlternatives( 'Reiniciar contraseña', text_content, to=[usuario.email] ) msg.attach_alternative(html_content, "text/html") msg.send()
def send_cancel_email(appointment): current_site = Site.objects.get_current() current_site_domain = "http://" + current_site.domain c = Context( { "appointment": appointment, "customer": appointment.customer, "client": appointment.client, "event": appointment.event, "current_site_domain": current_site_domain, } ) customer_email = "{name} <{email}>".format(name=appointment.customer.name, email=appointment.customer.email) email_subject = render_to_string("appointments/email/cancel_notification_subject.txt", c).replace("\n", "") email_txt_body = render_to_string("appointments/email/cancel_notification_body.txt", c) email_html_body = render_to_string("appointments/email/cancel_notification_body.html", c) email_headers = {"X-Mailgun-Campaign-Id": "fg0ec"} email = EmailMultiAlternatives( email_subject, # subject email_txt_body, # body settings.REMINDER_FROM_EMAIL, # from [customer_email], # to # ['*****@*****.**'], # bcc reply_to=[settings.REMINDER_FROM_EMAIL], headers=email_headers, ) email.attach_alternative(email_html_body, "text/html") return email.send(fail_silently=False)
def email_submission(self, form_data, request, referrer): mail_to = re.compile('\s*[,;]+\s*').split(self.form_definition.email_to) mail_from = self.form_definition.email_from or None mail_subject = self.form_definition.email_subject or \ 'Form Submission - %s' % self.form_definition.name context = { 'form': self.form_definition, 'referrer': referrer, 'title': mail_subject, 'form_data': form_data, 'request': request, 'recipients': mail_to, } message = render_to_string('djangocms_forms/email_template/email.txt', context) message_html = render_to_string('djangocms_forms/email_template/email.html', context) email = EmailMultiAlternatives(mail_subject, message, mail_from, mail_to) email.attach_alternative(message_html, 'text/html') if self.form_definition.email_uploaded_files: for field, filedata in self.files.items(): filedata.open('r') content = filedata.read() filedata.close() email.attach(filedata.name, content, filedata.content_type) email.send(fail_silently=False)
def send_mail_template(subject, template, addr_from, addr_to, context=None, attachments=None, fail_silently=False, addr_bcc=None): """ Send email rendering text and html versions for the specified template name using the context dictionary passed in. """ if context is None: context = {} if attachments is None: attachments = [] # Allow for a single address to be passed in. if not hasattr(addr_to, "__iter__"): addr_to = [addr_to] if addr_bcc is not None and not hasattr(addr_bcc, "__iter__"): addr_bcc = [addr_bcc] # Loads a template passing in vars as context. render = lambda type: loader.get_template("%s.%s" % (template, type)).render(Context(context)) # Create and send email. msg = EmailMultiAlternatives(subject, render("txt"), addr_from, addr_to, addr_bcc) msg.attach_alternative(render("html"), "text/html") for attachment in attachments: msg.attach(*attachment) msg.send(fail_silently=fail_silently)
def forge_corporate_email(subject, html_body, text_body, to, extra_images={}, **kwargs): # related = MIMEMultipart("related") html_content = render_to_string( 'email/email.html', { 'body': html_body, 'subject': subject, 'corp_color': '#502c1d', 'BASE_URL': settings.BASE_URL, }, ) text_content = strip_tags( render_to_string( 'email/email_text.html', { 'body': text_body, 'subject': subject, 'corp_color': '#502c1d', 'BASE_URL': settings.BASE_URL, }, )) if 'from_email' in kwargs: from_email = kwargs.pop('from_email') else: from_email = settings.DEFAULT_FROM_EMAIL email = EmailMultiAlternatives(subject=subject, body=text_content, from_email=from_email, to=to, **kwargs) email.attach_alternative(html_content, 'text/html') img = open( os.path.join(os.path.dirname(__file__), '..', '..', 'static', 'images', 'email-logo.png'), 'rb', ).read() logo_image = MIMEImage(img) logo_image.add_header('Content-ID', '<email-logo.png>') logo_image.add_header('Content-Disposition', 'inline', filename='email-logo.png') logo_image.add_header('Content-Type', 'image/png', name='email-logo.png') email.attach(logo_image) for img_id, img_path in extra_images.items(): try: img = open(img_path, 'r').read() logo_image = MIMEImage(img) logo_image.add_header('Content-ID', '<{}>'.format(img_id)) logo_image.add_header('Content-Disposition', 'inline', filename=img_id) subtype = 'jpeg' if img_path.lower().endswith('png'): subtype = 'png' logo_image.add_header('Content-Type', 'image/{}'.format(subtype), name=img_id) email.attach(logo_image) except Exception: pass email.mixed_subtype = "related" return email
def send_email(recipients, subject, text_content=None, html_content=None, from_email=None, use_base_template=True, category=None, fail_silently=False, language=None, cc=None, bcc=None, attachments=None, headers=None, bypass_queue=False, bypass_hijacking=False, attach_files=None): """ Will send a multi-format email to recipients. Email may be queued through celery """ from django.conf import settings if not bypass_queue and hasattr( settings, 'MAILING_USE_CELERY') and settings.MAILING_USE_CELERY: from celery.execute import send_task return send_task('mailing.queue_send_email', [ recipients, subject, text_content, html_content, from_email, use_base_template, category, fail_silently, language if language else translation.get_language(), cc, bcc, attachments, headers, bypass_hijacking, attach_files ]) else: header_category_value = '%s%s' % ( settings.MAILING_HEADER_CATEGORY_PREFIX if hasattr( settings, 'MAILING_HEADER_CATEGORY_PREFIX') else '', category) # Check for sendgrid support and add category header # -------------------------------- if hasattr(settings, 'MAILING_USE_SENDGRID'): send_grid_support = settings.MAILING_USE_SENDGRID else: send_grid_support = False if not headers: headers = dict() if send_grid_support and category: headers['X-SMTPAPI'] = '{"category": "%s"}' % header_category_value # Check for Mailgun support and add label header # -------------------------------- if hasattr(settings, 'MAILING_USE_MAILGUN'): mailgun_support = settings.MAILING_USE_MAILGUN else: mailgun_support = False if not headers: headers = dict() if mailgun_support and category: headers['X-Mailgun-Tag'] = header_category_value # Ensure recipients are in a list # -------------------------------- if isinstance(recipients, basestring): recipients_list = [recipients] else: recipients_list = recipients # Check if we need to hijack the email # -------------------------------- if hasattr(settings, 'MAILING_MAILTO_HIJACK') and not bypass_hijacking: headers['X-MAILER-ORIGINAL-MAILTO'] = ','.join(recipients_list) recipients_list = [settings.MAILING_MAILTO_HIJACK] if not subject: raise MailerMissingSubjectError('Subject not supplied') # Send ascii, html or multi-part email # -------------------------------- if text_content or html_content: if use_base_template: prev_language = translation.get_language() language and translation.activate(language) text_content = render_to_string( 'mailing/base.txt', { 'mailing_text_body': text_content, 'mailing_subject': subject, 'settings': settings }) if text_content else None html_content = render_to_string( 'mailing/base.html', { 'mailing_html_body': html_content, 'mailing_subject': subject, 'settings': settings }) if html_content else None translation.activate(prev_language) msg = EmailMultiAlternatives( subject, text_content if text_content else html_content, from_email if from_email else settings.DEFAULT_FROM_EMAIL, recipients_list, cc=cc, bcc=bcc, attachments=attachments, headers=headers) if html_content and text_content: msg.attach_alternative(html_content, "text/html") elif html_content: # Only HTML msg.content_subtype = "html" # Attach files through attach_files helper # -------------------------------- if attach_files: for att in attach_files: # attachments are tuples of (filepath, mimetype, filename) with open(att[0], 'rb') as f: content = f.read() msg.attach(att[2], content, att[1]) # Send email # -------------------------------- msg.send(fail_silently=fail_silently) else: raise MailerInvalidBodyError('No text or html body supplied.')
import datetime
def send(self, to_addresses, from_address=None, context=None, attachments=None, cc=None, bcc=None): """ Send an email using EmailMultiAlternatives with text and html. :param to_addresses: a string or a list of addresses :param from_address: if None the settings.DEFAULT_FROM_EMAIL is used :param context: a dictionary or a Context object used for rendering the templates. :param attachments: a list of (filepath, content, mimetype) triples (see https://docs.djangoproject.com/en/1.9/topics/email/) or Documents :param bcc: :param cc: :return: """ # The next line will throw a TemplateDoesNotExist if html template cannot be found html_template = loader.get_template(self.html_template) # render html html_body = _render(html_template, context) if self.txt_template is not None: txt_template = loader.get_template(self.txt_template) txt_body = _render(txt_template, context) else: txt_body = strip_tags(html_body) # build message if isinstance(to_addresses, six.string_types): to_addresses = [to_addresses] if attachments is None: attachments = [] if attachments is not None and not isinstance(attachments, list): attachments = list(attachments) if attachments is None: attachments = [] # Convert Documents to (filename, content, mime) attachment _attachments = [] for attachment in attachments: if isinstance(attachment, Document): filename = str(attachment) content = attachment.file.read() mime = mimetypes.guess_type(attachment.filename)[0] _attachments.append((filename, content, mime)) else: _attachments.append(attachment) msg = EmailMultiAlternatives(self.subject, txt_body, from_email=from_address, to=to_addresses, attachments=_attachments, cc=cc, bcc=bcc) msg.attach_alternative(html_body, 'text/html') try: msg.send(fail_silently=False) return msg except Exception as e: logger.exception("Error while sending email to {}: {}".format( to_addresses, e)) return None
def send_templated_mail(template_name, email_context, recipients, sender=None, bcc=None, fail_silently=False, files=None): """ send_templated_mail() is a warpper around Django's e-mail routines that allows us to easily send multipart (text/plain & text/html) e-mails using templates that are stored in the database. This lets the admin provide both a text and a HTML template for each message. template_name is the slug of the template to use for this message (see models.EmailTemplate) email_context is a dictionary to be used when rendering the template recipients can be either a string, eg '*****@*****.**', or a list of strings. sender should contain a string, eg 'My Site <*****@*****.**>'. If you leave it blank, it'll use settings.DEFAULT_FROM_EMAIL as a fallback. bcc is an optional list of addresses that will receive this message as a blind carbon copy. fail_silently is passed to Django's mail routine. Set to 'True' to ignore any errors at send time. files can be a list of file paths to be attached, or it can be left blank. eg ('/tmp/file1.txt', '/tmp/image.png') """ from django.conf import settings from django.core.mail import EmailMultiAlternatives from django.template import loader, Context from helpdesk.models import EmailTemplate import os context = Context(email_context) locale = getattr(context['queue'], 'locale', '') if not locale: locale = 'en' t = None try: t = EmailTemplate.objects.get(template_name__iexact=template_name, locale=locale) except EmailTemplate.DoesNotExist: pass if not t: try: t = EmailTemplate.objects.get(template_name__iexact=template_name, locale__isnull=True) except EmailTemplate.DoesNotExist: return # just ignore if template doesn't exist if not sender: sender = settings.DEFAULT_FROM_EMAIL footer_file = os.path.join('helpdesk', locale, 'email_text_footer.txt') text_part = loader.get_template_from_string( "%s{%% include '%s' %%}" % (t.plain_text, footer_file) ).render(context) email_html_base_file = os.path.join('helpdesk', locale, 'email_html_base.html') ''' keep new lines in html emails ''' from django.utils.safestring import mark_safe if context.has_key('comment'): html_txt = context['comment'] html_txt = html_txt.replace('\r\n', '<br>') context['comment'] = mark_safe(html_txt) html_part = loader.get_template_from_string( "{%% extends '%s' %%}{%% block title %%}%s{%% endblock %%}{%% block content %%}%s{%% endblock %%}" % (email_html_base_file, t.heading, t.html) ).render(context) subject_part = loader.get_template_from_string( "{{ ticket.ticket }} {{ ticket.title|safe }} %s" % t.subject ).render(context) if type(recipients) == str: if recipients.find(','): recipients = recipients.split(',') elif type(recipients) != list: recipients = [recipients,] msg = EmailMultiAlternatives( subject_part, text_part, sender, recipients, bcc=bcc) msg.attach_alternative(html_part, "text/html") if files: if type(files) != list: files = [files,] for file in files: msg.attach_file(file) return msg.send(fail_silently)
def send_emails(): current_date = datetime.now() one_month_ago = monthdelta(current_date, -1) # retrieve projects created in the past month matching each users' project email preferences projects_matching_preferences = UserEmailPreference.objects.raw( """ SELECT MAX(id) as id, user_id, project_id, MAX(name) AS name, MAX(owner_id) AS owner_id, MAX(first_name) AS first_name, MAX(last_name) AS last_name, MAX("datePosted") AS "datePosted" FROM ( SELECT api_useremailpreference.id, user_id, project_id, api_project.name, api_project.owner_id, api_puser.first_name, api_puser.last_name, api_project."datePosted" FROM api_useremailpreference JOIN api_agerangeproject ON api_agerangeproject."ageRange" = api_useremailpreference."preferenceValue" AND api_useremailpreference."preferenceName" = 'ageRange' AND api_useremailpreference.type = '1' JOIN api_project ON api_project.id = api_agerangeproject.project_id JOIN api_puser ON api_puser.id = api_project.owner_id WHERE api_project.owner_id != api_useremailpreference.user_id AND api_project."datePosted" >= %s UNION SELECT api_useremailpreference.id, user_id, project_id, api_project.name, api_project.owner_id, api_puser.first_name, api_puser.last_name, api_project."datePosted" FROM api_useremailpreference JOIN api_deliverymodeproject ON api_deliverymodeproject."deliveryMode" = api_useremailpreference."preferenceValue" AND api_useremailpreference."preferenceName" = 'deliveryMode' AND api_useremailpreference.type = '1' JOIN api_project ON api_project.id = api_deliverymodeproject.project_id JOIN api_puser ON api_puser.id = api_project.owner_id WHERE api_project.owner_id != api_useremailpreference.user_id AND api_project."datePosted" >= %s UNION SELECT api_useremailpreference.id, user_id, project_id, api_project.name, api_project.owner_id, api_puser.first_name, api_puser.last_name, api_project."datePosted" FROM api_useremailpreference JOIN api_deliverymodeproject ON api_useremailpreference."preferenceValue" = 'Other' AND api_deliverymodeproject."deliveryMode" NOT IN ('Afterschool programs', 'Camps', 'Clubs', 'In-school Programming', 'Summer Youth Employment Opportunities', 'Special Interest/Short Term', 'Fairs/Events') AND api_useremailpreference."preferenceName" = 'deliveryMode' AND api_useremailpreference.type = '1' JOIN api_project ON api_project.id = api_deliverymodeproject.project_id JOIN api_puser ON api_puser.id = api_project.owner_id WHERE api_project.owner_id != api_useremailpreference.user_id AND api_project."datePosted" >= %s UNION SELECT api_useremailpreference.id, user_id, project_id, api_project.name, api_project.owner_id, api_puser.first_name, api_puser.last_name, api_project."datePosted" FROM api_useremailpreference JOIN api_topicsproject ON api_topicsproject."researchTopic" = api_useremailpreference."preferenceValue" AND api_useremailpreference."preferenceName" = 'researchTopic' AND api_useremailpreference.type = '1' JOIN api_project ON api_project.id = api_topicsproject.project_id JOIN api_puser ON api_puser.id = api_project.owner_id WHERE api_project.owner_id != api_useremailpreference.user_id AND api_project."datePosted" >= %s UNION SELECT api_useremailpreference.id, user_id, project_id, api_project.name, api_project.owner_id, api_puser.first_name, api_puser.last_name, api_project."datePosted" FROM api_useremailpreference JOIN api_topicsproject ON api_useremailpreference."preferenceValue" = 'Other' AND api_topicsproject."researchTopic" NOT IN ('Animal Science', 'Agriculture', 'Career Readiness', 'Civic Engagement', 'Diversity Equity & Inclusion', 'Education & Learning', 'Energy', 'Environment & Sustainability', 'Families', 'Gardening & Horticulture', 'Health & Wellness', 'Intergenerational Engagement', 'Life Skills', 'Media & Technology', 'Motivation', 'Nutrition', 'Outdoor Education', 'Parenting', 'Peer Relationships', 'Positive Youth Development', 'Policy Analysis', 'Program Evaluation', 'Risk Behavior', 'Self & Identity', 'Science Technology Engineering & Math (STEM)', 'Volunteer Engagement', 'Youth/Adult Relationships') AND api_useremailpreference."preferenceName" = 'researchTopic' AND api_useremailpreference.type = '1' JOIN api_project ON api_project.id = api_topicsproject.project_id JOIN api_puser ON api_puser.id = api_project.owner_id WHERE api_project.owner_id != api_useremailpreference.user_id AND api_project."datePosted" >= %s ) as temp GROUP BY user_id, project_id ORDER BY user_id, name; """, [one_month_ago, one_month_ago, one_month_ago, one_month_ago, one_month_ago] ) # retrieve users joined in the past month matching each users' user email preferences users_matching_preferences = UserEmailPreference.objects.raw( """ SELECT MAX(id) as id, user_id, matched_user_id, MAX(first_name) as first_name, MAX(last_name) as last_name, MAX(role) as role, MAX(location) as location, MAX(date_joined) as date_joined FROM ( SELECT api_useremailpreference.id, api_useremailpreference.user_id, api_puser.id AS matched_user_id, api_puser.first_name, api_puser.last_name, api_puser.role, api_puser.location, api_puser.date_joined FROM api_useremailpreference JOIN api_agerangeuser ON api_agerangeuser."ageRange" = api_useremailpreference."preferenceValue" AND api_useremailpreference."preferenceName" = 'ageRange' AND api_useremailpreference.type = '2' JOIN api_puser ON api_puser.id = api_agerangeuser.user_id WHERE api_puser.id != api_useremailpreference.user_id AND api_puser.date_joined >= %s UNION SELECT api_useremailpreference.id, api_useremailpreference.user_id, api_puser.id AS matched_user_id, api_puser.first_name, api_puser.last_name, api_puser.role, api_puser.location, api_puser.date_joined FROM api_useremailpreference JOIN api_researchinterestuser ON api_researchinterestuser."researchInterest" = api_useremailpreference."preferenceValue" AND api_useremailpreference."preferenceName" = 'researchInterest' AND api_useremailpreference.type = '2' JOIN api_puser ON api_puser.id = api_researchinterestuser.user_id WHERE api_puser.id != api_useremailpreference.user_id AND api_puser.date_joined >= %s UNION SELECT api_useremailpreference.id, api_useremailpreference.user_id, api_puser.id AS matched_user_id, api_puser.first_name, api_puser.last_name, api_puser.role, api_puser.location, api_puser.date_joined FROM api_useremailpreference JOIN api_researchinterestuser ON api_useremailpreference."preferenceValue" = 'Other' AND api_researchinterestuser."researchInterest" NOT IN ('Animal Science', 'Agriculture', 'Career Readiness', 'Civic Engagement', 'Diversity Equity & Inclusion', 'Education & Learning', 'Energy', 'Environment & Sustainability', 'Families', 'Gardening & Horticulture', 'Health & Wellness', 'Intergenerational Engagement', 'Life Skills', 'Media & Technology', 'Motivation', 'Nutrition', 'Outdoor Education', 'Parenting', 'Peer Relationships', 'Positive Youth Development', 'Policy Analysis', 'Program Evaluation', 'Risk Behavior', 'Self & Identity', 'Science Technology Engineering & Math (STEM)', 'Volunteer Engagement', 'Youth/Adult Relationships') AND api_useremailpreference."preferenceName" = 'researchInterest' AND api_useremailpreference.type = '2' JOIN api_puser ON api_puser.id = api_researchinterestuser.user_id WHERE api_puser.id != api_useremailpreference.user_id AND api_puser.date_joined >= %s UNION SELECT api_useremailpreference.id, api_useremailpreference.user_id, api_puser.id AS matched_user_id, api_puser.first_name, api_puser.last_name, api_puser.role, api_puser.location, api_puser.date_joined FROM api_useremailpreference JOIN api_deliverymodeuser ON api_deliverymodeuser."deliveryMode" = api_useremailpreference."preferenceValue" AND api_useremailpreference."preferenceName" = 'deliveryMode' AND api_useremailpreference.type = '2' JOIN api_puser ON api_puser.id = api_deliverymodeuser.user_id WHERE api_puser.id != api_useremailpreference.user_id AND api_puser.date_joined >= %s UNION SELECT api_useremailpreference.id, api_useremailpreference.user_id, api_puser.id AS matched_user_id, api_puser.first_name, api_puser.last_name, api_puser.role, api_puser.location, api_puser.date_joined FROM api_useremailpreference JOIN api_deliverymodeuser ON api_useremailpreference."preferenceValue" = 'Other' AND api_deliverymodeuser."deliveryMode" NOT IN ('Afterschool programs', 'Camps', 'Clubs', 'In-school Programming', 'Summer Youth Employment Opportunities', 'Special Interest/Short Term', 'Fairs/Events') AND api_useremailpreference."preferenceName" = 'deliveryMode' AND api_useremailpreference.type = '2' JOIN api_puser ON api_puser.id = api_deliverymodeuser.user_id WHERE api_puser.id != api_useremailpreference.user_id AND api_puser.date_joined >= %s ) as temp GROUP BY user_id, matched_user_id ORDER BY user_id, first_name, last_name; """, [one_month_ago, one_month_ago, one_month_ago, one_month_ago, one_month_ago] ) # get dictionary containing the newsletter contents of all subscribed users user_emails = build_emails(projects_matching_preferences, users_matching_preferences) # get the email addresses of each subscribed user user_ids = list(user_emails.keys()) users = PUser.public_objects.filter(pk__in=user_ids) # send email to each subscribed user for user in users: plaintext = get_template("newsletter.txt") htmly = get_template("newsletter.html") month = current_date.strftime('%B') subject = "PRYDE Connect %s Newsletter" % month from_email = "*****@*****.**" to = user.email data = { "first_name": user.first_name, "last_name": user.last_name, "content": user_emails[user.id] } text_content = plaintext.render(data) html_content = htmly.render(data) msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") msg.send(fail_silently=False)
# # send_mail( # '来自www.liujiangblog.com的测试邮件', # '欢迎访问www.liujiangblog.com,这里是刘江的博客和教程站点,本站专注于Python和Django技术的分享!', # '*****@*****.**', # ['*****@*****.**'], # ) # 对于send_mail方法,第一个参数是邮件主题subject;第二个参数是邮件具体内容;第三个参数是邮件发送方,需要和你settings中的一致; # 第四个参数是接受方的邮件地址列表。请按你自己实际情况修改发送方和接收方的邮箱地址。 # # 另外,由于我们是单独运行send_mail.py文件,所以无法使用Django环境,需要通过os模块对环境变量进行设置,也就是: # # os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' # 发送HTML格式的邮件 # 通常情况下,我们发送的邮件内容都是纯文本格式。但是很多情况下,我们需要发送带有HTML格式的内容,比如说超级链接。 # 一般情况下,为了安全考虑,很多邮件服务提供商都会禁止使用HTML内容,幸运的是对于以http和https开头的链接还是可以点击的。 import os from django.core.mail import EmailMultiAlternatives os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite_1.settings' if __name__ == '__main__': subject, from_email, to = '来自www.liujiangblog.com的测试邮件', '*****@*****.**', '*****@*****.**' text_content = '欢迎访问www.liujiangblog.com,这里是刘江的博客和教程站点,专注于Python和Django技术的分享!' html_content = '<p>欢迎访问<a href="http://www.liujiangblog.com" target=blank>www.liujiangblog.com</a>,这里是刘江的博客和教程站点,专注于Python和Django技术的分享!</p>' msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") msg.send()
def vacancy_details(request, criteria): if request.method == 'POST' and 'vacancy_apply' in request.POST: form = VacancyForm(request.POST, request.FILES) back = request.META.get('HTTP_REFERER') if form.is_valid(): name = request.POST.get('name') form_email = request.POST.get('email') phone = request.POST.get('phone') photo = request.FILES.get('photo') cv = request.FILES.get('cv') position = request.POST.get('position') if ApplicantData.objects.filter(email=form_email).exists(): messages.error( request, 'Vacancy already applied from email ' + form_email, "alert alert-warning alert-dismissible") return redirect(back) c = { 'Name': name, 'Email': form_email, 'Contact': phone, 'Position': position } text_content = render_to_string('vacancy_email_template/email.txt', c) html_content = render_to_string( 'vacancy_email_template/email.html', c) email = EmailMultiAlternatives('Vacancy Applied for ' + position, text_content) email.attach_alternative(html_content, "text/html") email.attach(cv.name, cv.read(), cv.content_type) email.attach(photo.name, photo.read(), photo.content_type) email.to = ['*****@*****.**'] email.send() applicant_obj = ApplicantData(name=name, email=form_email, contact=phone, photo=photo, cv=cv, position=position) applicant_obj.save() messages.success(request, 'Vacancy Applied Successfully', "alert alert-success alert-dismissible") return redirect(back) get_view = Vacancy.objects.get(slug=criteria) get_view.page_visit += 1 get_view.save() data = { 'VacancyForm': form, 'title': get_view.title, 'description': get_view.job_description, 'url': "https://3kanyatravel.com.np//vacancy-details/" + get_view.slug, 'vacancydetails': Vacancy.objects.get(slug=criteria) } return render(request, 'pages/vacancy/vacancy-details.view.html', data) else: get_view = Vacancy.objects.get(slug=criteria) get_view.page_visit += 1 get_view.save() data = { 'VacancyForm': VacancyForm, 'title': get_view.title, 'description': get_view.job_description, 'url': "https://3kanyatravel.com.np/vacancy-details/" + get_view.slug, 'vacancydetails': Vacancy.objects.get(slug=criteria) } return render(request, 'pages/vacancy/vacancy-details.view.html', data)
def _send_campanha_thread(campanha_id, user_id, emails_list, from_email=settings.DEFAULT_FROM_EMAIL): def splip_emails(emails, ite=100): ini = 0 for i in range(ite, len(emails), ite): yield emails[ini:i] ini = i if len(emails) > ini: yield emails[ini:len(emails)] campanha = Campanha.objects.get(pk=campanha_id) subject = campanha.assunto text_content = subject campanha_ct = ContentType.objects.get_for_model(campanha) # Renderiza o template, se não consegui mata a thread template = u'%s<img src="%s%s" />' % ( campanha.template, settings.SITE_HOST, campanha.get_qtde_views_url()) try: template_content = get_template(template) except: try: template_content = Template(template) except: LogEntry.objects.log_action( user_id=user_id, content_type_id=campanha_ct.pk, object_id=campanha.pk, object_repr=u"%s" % campanha, action_flag=CHANGE, change_message= u'[ERROR] Erro ao montar template para envio.') Campanha.objects.filter(pk=campanha_id).update( qtde_erros=len(emails_list), status='R') return html_content = template_content.render(Context({})) LogEntry.objects.log_action( user_id=user_id, content_type_id=campanha_ct.pk, object_id=campanha.pk, object_repr=u"%s" % campanha, action_flag=CHANGE, change_message=u'[INFO] Iniciado o envio de %d emails' % len(emails_list)) for emails in splip_emails(emails_list): # Cria a mensagem msg = EmailMultiAlternatives(subject, text_content, from_email, bcc=emails) msg.attach_alternative(html_content, 'text/html; charset=UTF-8') # Realiza até 3 tentativas de enviar tentativas = 0 while tentativas < 3: # Interromer thread caso tenha marcado o status como Interrompido if Campanha.objects.get(pk=campanha_id).status == 'I': LogEntry.objects.log_action( user_id=user_id, content_type_id=campanha_ct.pk, object_id=campanha.pk, object_repr=u"%s" % campanha, action_flag=CHANGE, change_message= u'[INFO] Processo interrompido pelo usuário.') return try: msg.send() break except: LogEntry.objects.log_action( user_id=user_id, content_type_id=campanha_ct.pk, object_id=campanha.pk, object_repr=u"%s" % campanha, action_flag=CHANGE, change_message= u'[ERROR] Falha na %sª/3 tentativa de envio para: %s.' % ( tentativas + 1, u", ".join(emails), )) tentativas += 1 sleep(30) if tentativas == 3: print '[ERROR] Deu erro!' LogEntry.objects.log_action( user_id=user_id, content_type_id=campanha_ct.pk, object_id=campanha.pk, object_repr=u"%s" % campanha, action_flag=CHANGE, change_message= u'[ERROR] Erro ao enviar emails para: %s.' % u", ".join(emails)) Campanha.objects.filter(pk=campanha_id).update( qtde_erros=campanha.lista.listacadastro_set.filter( pessoa__status_email__in=( 'A', 'N', )).count() - F('qtde_envio'), status='E') return else: # Atualiza o número de envios Campanha.objects.filter(pk=campanha_id).update( qtde_envio=F('qtde_envio') + len(emails)) LogEntry.objects.log_action( user_id=user_id, content_type_id=campanha_ct.pk, object_id=campanha.pk, object_repr=u"%s" % campanha, action_flag=CHANGE, change_message=u'[INFO] Envio Finalizado') # Atualiza o status Campanha.objects.filter(pk=campanha_id).update(status='F')
def run (self): msg = EmailMultiAlternatives(self.subject, self.body, self.from_email, self.recipient_list) if self.html: msg.attach_alternative(self.html, "text/html") msg.send(self.fail_silently)
class Sender(Base_Website): def Attach_Image(self, image_path, image_name): img_data = open(BASE_DIR + image_path, 'rb').read() img = MIMEImage(img_data, 'png') img.add_header('Content-Id', '<{0}>'.format(image_name)) img.add_header("Content-Disposition", "inline", filename=image_name) self.email.attach(img) def Send_Forgot_Password_Link(self, content, recipient): title = Text(self, 32) html_file = 'forgot_password.html' recipient = [recipient] self.Send_Email(title, content, recipient, html_file) def Send_Register_Approved_Link(self, content, recipient): title = Text(self, 33) html_file = 'register_approved.html' recipient = [recipient] self.Send_Email(title, content, recipient, html_file) def Send_Payment_Approved(self, content, recipient, pdf): title = Text(self, 34) html_file = 'payment_approved.html' recipient = [recipient, ROOT_EMAIL] pdf = { 'name': Text(self, 106), 'file': pdf.content, } self.Send_Email(title, content, recipient, html_file, pdf=pdf) def Send_Payment_Failure(self, content, recipient): title = Text(self, 151) html_file = 'payment_failure.html' recipient = [recipient, ROOT_EMAIL] self.Send_Email(title, content, recipient, html_file) def Send_Contact_Question(self, title, content, recipient): html_file = 'contact_question.html' reply_to = [recipient] recipient = [recipient, ROOT_EMAIL] self.Send_Email(title, content, recipient, html_file, reply_to) def Send_Root_Email(self, title, context, recipient): html_file = 'send_root_email.html' reply_to = [ROOT_EMAIL] recipient = [recipient, ROOT_EMAIL] self.Send_Email(title, context, recipient, html_file, reply_to) def Send_Notification(self, title, context, model_object): client_email = model_object.payment.user.email html_file = 'notification.html' reply_to = [ROOT_EMAIL] recipients = [] if model_object.send_to_client: recipients.append(client_email) if model_object.send_to_root: recipients.append(ROOT_EMAIL) context['payment'] = model_object.payment self.Send_Email(title, context, recipients, html_file, reply_to) def Send_Email(self, title, content, recipient, html_file, reply_to=None, pdf=None): self.context = content html = self.Render_HTML('sender/' + html_file) self.email = EmailMultiAlternatives( subject=title, body=html.content.decode(), from_email='Medinox <*****@*****.**>', to=recipient, reply_to=reply_to) if pdf: self.email.attach(pdf['name'], pdf['file'], 'application/pdf') self.email.attach_alternative(html.content.decode(), 'text/html') Email_Thread(self.email).start() def __init__(self, _object): Base_Website.__init__(self, _object) self.email = None
def enviar_cotizacion(self, cotizacion, user, email_adicional=None): version_cotizacion = cotizacion.version from_ventas_email = EmailConfiguration.objects.first( ).email_ventas_from if not from_ventas_email: from_ventas_email = settings.DEFAULT_FROM_EMAIL enviar_como = user.user_extendido.email_envio_como if enviar_como: enviar_como = '%s - %s' % (user.user_extendido.email_envio_como, user.get_full_name()) else: enviar_como = 'ODECOPACK - %s' % (user.get_full_name()) if user.email: email_split = user.email.split('@') if email_split[-1] in list( DominiosEmail.objects.values_list('dominio', flat=True).all()): from_email = "%s <%s>" % (enviar_como, user.email) else: from_email = "%s <%s>" % (enviar_como, from_ventas_email) else: from_email = "%s <%s>" % (enviar_como, from_ventas_email) if email_adicional: to = [cotizacion.email, email_adicional] else: to = [cotizacion.email] subject = "%s - %s" % ('Cotizacion', cotizacion.nro_cotizacion) if version_cotizacion > 1: subject = "%s, version %s" % (subject, cotizacion.version) ctx = { 'object': cotizacion, } try: colaborador = Colaborador.objects.get(usuario__user=user) except Colaborador.DoesNotExist: colaborador = None if not cotizacion.cliente_nuevo: colaboradores = SucursalBiable.objects.values( 'vendedor_real__colaborador_id').filter( cliente_id=cotizacion.cliente_biable_id, vendedor_real__isnull=False).distinct() if colaboradores.exists(): if colaboradores.count() == 1: colaborador = Colaborador.objects.get( pk=colaboradores.first() ['vendedor_real__colaborador_id']) cotizacion.usuario = colaborador.usuario.user cotizacion.save() else: colaborador = Colaborador.objects.get(usuario__user=user) if colaborador: if colaborador.foto_perfil: url_avatar = colaborador.foto_perfil.url ctx['avatar'] = url_avatar nombre_archivo_cotizacion = "Cotizacion Odecopack - CB %s.pdf" % ( cotizacion.id) if version_cotizacion > 1: ctx['version'] = cotizacion.version nombre_archivo_cotizacion = "Cotizacion Odecopack - CB %s ver %s.pdf" % ( cotizacion.id, cotizacion.version) text_content = render_to_string('cotizaciones/emails/cotizacion.html', ctx) html_content = get_template( 'cotizaciones/emails/cotizacion.html').render(Context(ctx)) output = BytesIO() HTML(string=html_content).write_pdf(target=output) msg = EmailMultiAlternatives(subject, text_content, from_email, to=to, reply_to=[user.email]) msg.attach_alternative(html_content, "text/html") msg.attach(nombre_archivo_cotizacion, output.getvalue(), 'application/pdf') if cotizacion.mis_imagenes: for imagen in cotizacion.mis_imagenes.all(): try: docfile = imagen.imagen.read() if docfile: nombre_archivo = imagen.imagen.name.split("/")[-1] msg.attach(nombre_archivo, docfile) docfile.close() else: pass except: pass msg.send() # Envio al asesor msg.from_email = "Confirmación <*****@*****.**>" msg.to = [user.email] msg.reply_to = None msg.send() output.close() cotizacion.save() if not cotizacion.cliente_nuevo: seguimiento = SeguimientoComercialCliente() seguimiento.cotizacion = cotizacion seguimiento.creado_por = self.request.user seguimiento.cliente = cotizacion.cliente_biable observacion_adicional = "<p> Valor Cotización: " + str( cotizacion.total) + "</p>" if cotizacion.descuento: observacion_adicional += "<p> Descuento Cotización: " + str( cotizacion.descuento) + "</p>" seguimiento.observacion_adicional = observacion_adicional if version_cotizacion > 1: seguimiento.tipo_accion = "Envío version " + str( version_cotizacion) else: seguimiento.tipo_accion = "Nueva" seguimiento.save()
def send_place_created_notifications(request, response): config = get_shareabouts_config(settings.SHAREABOUTS.get('CONFIG')) config.update(settings.SHAREABOUTS.get('CONTEXT', {})) # Before we start, check whether we're configured to send at all on new # place. should_send = config.get('notifications', {}).get('on_new_place', False) if not should_send: return # First, check that we have all the settings and data we need. Do not bail # after each error, so that we can report on all the validation problems # at once. errors = [] try: # The reuest has any potentially private data fields. requested_place = json.loads(request.body) except ValueError: errors.append('Received invalid place JSON from request: %r' % (request.body, )) try: # The response has things like ID and cretated datetime try: response.render() except: pass place = json.loads(response.content) except ValueError: errors.append('Received invalid place JSON from response: %r' % (response.content, )) try: from_email = settings.EMAIL_ADDRESS except AttributeError: errors.append( 'EMAIL_ADDRESS setting must be configured in order to send notification emails.' ) try: email_field = config.get('notifications', {}).get('submitter_email_field', 'submitter_email') recipient_email = requested_place['properties'][email_field] except KeyError: errors.append( 'No "%s" field found on the place. Be sure to configure the "notifications.submitter_email_field" property if necessary.' % (email_field, )) # Bail if any errors were found. Send all errors to the logs and otherwise # fail silently. if errors: for error_msg in errors: log.error(error_msg) return # If the user didn't provide an email address, then no need to go further. if not recipient_email: return # Set optional values bcc_list = getattr(settings, 'EMAIL_NOTIFICATIONS_BCC', []) # If we didn't find any errors, then render the email and send. context_data = RequestContext(request, { 'place': place, 'email': recipient_email, 'config': config, }) subject = render_to_string('new_place_email_subject.txt', context_data) body = render_to_string('new_place_email_body.txt', context_data) try: html_body = render_to_string('new_place_email_body.html', context_data) except TemplateDoesNotExist: html_body = None # connection = smtp.EmailBackend( # host=..., # port=..., # username=..., # use_tls=...) # NOTE: In Django 1.7+, send_mail can handle multi-part email with the # html_message parameter, but pre 1.7 cannot and we must construct the # multipart message manually. msg = EmailMultiAlternatives(subject, body, from_email, to=[recipient_email], bcc=bcc_list) #, # connection=connection) if html_body: msg.attach_alternative(html_body, 'text/html') msg.send() return
def mailWai(subject, message, sender, to, bcc=[]): msg = EmailMultiAlternatives(subject, strip_tags(message), sender, to, bcc) msg.attach_alternative(message, "text/html") msg.send()
def build_email( template_prefix: str, to_user_id: Optional[int] = None, to_email: Optional[str] = None, from_name: Optional[str] = None, from_address: Optional[str] = None, reply_to_email: Optional[str] = None, context: Optional[Dict[str, Any]] = None) -> EmailMultiAlternatives: # Callers should pass exactly one of to_user_id and to_email. assert (to_user_id is None) ^ (to_email is None) if to_user_id is not None: to_user = get_user_profile_by_id(to_user_id) # Change to formataddr((to_user.full_name, to_user.email)) once # https://github.com/zulip/zulip/issues/4676 is resolved to_email = to_user.email if context is None: context = {} context.update({ 'support_email': FromAddress.SUPPORT, 'email_images_base_uri': settings.ROOT_DOMAIN_URI + '/static/images/emails', 'physical_address': settings.PHYSICAL_ADDRESS, }) subject = loader.render_to_string( template_prefix + '.subject', context=context, using='Jinja2_plaintext').strip().replace('\n', '') message = loader.render_to_string(template_prefix + '.txt', context=context, using='Jinja2_plaintext') try: html_message = loader.render_to_string(template_prefix + '.html', context) except TemplateDoesNotExist: emails_dir = os.path.dirname(template_prefix) template = os.path.basename(template_prefix) compiled_template_prefix = os.path.join(emails_dir, "compiled", template) html_message = loader.render_to_string( compiled_template_prefix + '.html', context) if from_name is None: from_name = "Zulip" if from_address is None: from_address = FromAddress.NOREPLY from_email = formataddr((from_name, from_address)) reply_to = None if reply_to_email is not None: reply_to = [reply_to_email] # Remove the from_name in the reply-to for noreply emails, so that users # see "noreply@..." rather than "Zulip" or whatever the from_name is # when they reply in their email client. elif from_address == FromAddress.NOREPLY: reply_to = [FromAddress.NOREPLY] mail = EmailMultiAlternatives(subject, message, from_email, [to_email], reply_to=reply_to) if html_message is not None: mail.attach_alternative(html_message, 'text/html') return mail
def handle(self, *args, **options): from applications.delivery.models import Delivery try: deliveryes = Delivery.objects.filter( delivery_test=False, send_test=True, send_general=False, type__in=[ 1, 2, 3, ], ) except Delivery.DoesNotExist: deliveryes = None else: from applications.delivery.models import EmailMiddleDelivery for delivery in deliveryes: # print 'delivery', delivery try: EmailMiddleDelivery.objects.\ get(delivery=delivery, send_test=False, send_general=True, updated_at__lte=delivery.updated_at, ) except: """ Создаем ссылочку на отсылку рассылки """ email_middle_delivery = EmailMiddleDelivery() email_middle_delivery.delivery = delivery email_middle_delivery.delivery_test_send = False email_middle_delivery.delivery_send = True email_middle_delivery.save() """ Закрываем отсылку теста в самой рассылке """ delivery.send_general = True delivery.save() """ Отсылаем тестовое письмо """ from django.utils.html import strip_tags EMAIL_USE_TLS = True EMAIL_HOST = 'smtp.yandex.ru' EMAIL_PORT = 587 EMAIL_HOST_USER = '******' EMAIL_HOST_PASSWORD = '' from django.core.mail import get_connection backend = get_connection( backend='django.core.mail.backends.smtp.EmailBackend', host=EMAIL_HOST, port=EMAIL_PORT, username=EMAIL_HOST_USER, password=EMAIL_HOST_PASSWORD, use_tls=EMAIL_USE_TLS, fail_silently=False, ) from django.core.mail import EmailMultiAlternatives from proj.settings import Email_MANAGER from applications.authModel.models import Email """ Создаем указатели на E-Mail адреса рассылки """ try: emails = Email.objects.filter(bad_email=False, ) except Email.DoesNotExist: emails = None """ Здесь нужно помудрить с коммитом """ from applications.delivery.models import EmailForDelivery from applications.delivery.utils import parsing i = 0 time = 0 for real_email in emails: i += 1 # if i < 125: # continue email = EmailForDelivery.objects.create( delivery=email_middle_delivery, email=real_email, ) """ Отсылка """ msg = EmailMultiAlternatives( subject=delivery.subject, body=strip_tags( parsing( value=delivery.html, key=email.key, ), ), from_email='*****@*****.**', to=[ real_email.email, ], connection=backend, ) msg.attach_alternative( content=parsing( value=delivery.html, key=email.key, ), mimetype="text/html", ) msg.content_subtype = "html" try: msg.send(fail_silently=False, ) except Exception as e: msg = EmailMultiAlternatives( subject='Error for subject: %s' % delivery.subject, body= 'Error: %s - E-Mail: %s - real_email.pk: %d' % ( e, real_email.email, real_email.pk, ), from_email='*****@*****.**', to=[ '*****@*****.**', ], connection=backend, ) msg.send(fail_silently=True, ) else: print 'i: ', i, 'Pk: ', real_email.pk, ' - ', real_email.email from random import randrange time1 = randrange( 6, 12, ) time2 = randrange( 6, 12, ) time += time1 + time2 print 'Time1: ', time1, ' Time2: ', time2, ' Time all: ', time1 + time2, ' average time: ', time / i from time import sleep sleep(time1, ) print 'Next' sleep(time2, )
def parse_csv(self): """ CHUNK IS A DATAFRAME """ for chunk in pd.read_csv(self.file_name, chunksize=self.CHUNK_SIZE): columns = self.strip_headers(chunk) self.rename_column_headers_for_db(chunk) try: if self.func_name.__name__ == 'upload_temporary_first_allocation': error_rows.extend( self.func_name(chunk, self.tenant, self.client_attribute, self.user, self.job_id)) elif self.func_name.__name__ == 'upload_temporal_ratio': error_rows.extend( self.func_name(chunk, self.tenant, self.client_attribute, self.user, self.temporal_ratio_type)) elif self.func_name.__name__ == 'upload_current_store_inventory': error_rows.extend( self.func_name(chunk, self.tenant, self.client_attribute, self.user, self.date_time, self.channel)) elif self.channel and self.date_time: error_rows.extend( self.func_name(chunk, self.tenant, self.client_attribute, self.user, self.date_time, self.channel)) elif self.channel or self.func_name.__name__ in [ 'upload_primary_sale', 'upload_daily_sale' ]: error_rows.extend( self.func_name(chunk, self.tenant, self.client_attribute, self.user, self.channel)) elif self.date_time: error_rows.extend( self.func_name(chunk, self.tenant, self.client_attribute, self.user, self.date_time)) else: if self.func_name == upload_product_master: error_rows.extend( self.func_name(chunk, self.tenant, self.client_attribute, self.user, self.new_data)) else: error_rows.extend( self.func_name(chunk, self.tenant, self.client_attribute, self.user)) success_row_count += len(chunk) except Exception as e: # TODO(ANUBHAV): IMPLEMENT LOGGING try: self.document.status = Document.FAILED self.document.errors = { 'parser_error': 'Error encountered in parser', 'error_details': e.args[0] } self.document.save() except AttributeError: pass return False if not self.func_name.__name__ in [ 'upload_attribute_ratios', 'upload_festive_uplift', 'upload_temporal_ratio', 'upload_optional_availability', 'upload_availability_decay_rate' ]: upload_to_s3(self.file_name) os.remove(self.file_name) try: default_from_email = settings.EMAIL_HOST_USER error_row_count = len(error_rows) success_row_count -= error_row_count if error_rows: error_df = pd.DataFrame(error_rows) error_file_name = self.file_name.split('/')[-1].split( '.')[0] + '_error.csv' error_df.to_csv(error_file_name) destination_path = settings.ERROR_FILE_PATH + error_file_name upload_to_s3(error_file_name, destination_path) os.remove(error_file_name) self.document.error_file_path = destination_path # error_rows = json.dumps(error_rows) # self.document.errors = error_rows self.document.success_row_count = success_row_count self.document.error_row_count = error_row_count self.document.status = Document.COMPLETED_WITH_ERRORS else: self.document.success_row_count = success_row_count self.document.status = Document.COMPLETED self.document.save() user = User.objects.get(id=self.user) plain_text = get_template('email_alerts/upload_success.txt') html_text = get_template('email_alerts/upload_success.html') context = { 'username': user.first_name, 'file_name': self.file_name } text_content = plain_text.render(context) html_content = html_text.render(context) subject = '{} File Upload Processed'.format(self.file_name) msg = EmailMultiAlternatives(subject, text_content, default_from_email, [user.email], reply_to=[settings.CLIENT_SUPPORT]) msg.attach_alternative(html_content, "text/html") msg.send() except: pass return True
from django.template.loader import render_to_string all_callbackees = [] their_callbacks = [] #emails_sent for callbackee in Callbackee.objects.filter(net_id='aryehnc'): print 'here' all_callbackees.append(callbackee) current_callbacks = Callbacks.objects.filter(callbackee=callbackee) their_callbacks.append(current_callbacks) zipped = zip(all_callbackees, their_callbacks) # c = Context({'callbackee': existing_callbackee, 'group': Group.objects.get(name=datadict['group'])}) # html_content = render_to_string('email_for_callbackee.html', c) # email = EmailMultiAlternatives('yo', '') # email.attach_alternative(html_content, "text/html") # email.to = ['*****@*****.**'] # email.send() for callbackee, callbacks in zipped: c = Context({'callbackee': callbackee, 'callbacks': callbacks}) html_content = render_to_string('email_for_callbackee.html', c) email = EmailMultiAlternatives('Callbacks from Acaprez', '') email.attach_alternative(html_content, "text/html") email_address = '' email_address += callbackee.net_id email_address += '@princeton.edu' email.to = [email_address] email.send() callbackee.email_sent = True callbackee.save()
def checkout(request): cart = list((request.session.get('shopping_cart', {})).values()) # get the total amount of the orders total_amount = 0 for elem in cart: total_amount = (total_amount + float(elem['total_price'])) total_amount = total_amount # round up total amount to 2 decimal points total_amount = round(total_amount, 2) # check if delivery fees is needed if total_amount < 100.00: delivery_fee = 3.95 else: delivery_fee = 0.00 # total total_amount = round((total_amount + delivery_fee), 2) if request.method == "POST": street_address = f"{request.POST['street_address1']} {request.POST['street_address2']}" town_or_city = request.POST['town_or_city'] county = request.POST['county'] postcode = request.POST['postcode'] country = request.POST['country'] order_form = OrderForm(request.POST) payment_form = PaymentForm(request.POST) if order_form.is_valid() and payment_form.is_valid(): stripeToken = request.POST['stripe_id'] try: customer = stripe.Charge.create( amount=int(100*total_amount), # convert to cents currency='sgd', description=f"Charge for {request.user}: ${total_amount}", source = stripeToken ) if customer.paid: messages.success(request, "Payment successfully made. We will begin to process your order!") # create order if the charge was successful # 240220 added in address order = Order.objects.create( customer=request.user, stripe_token=stripeToken, street_address=street_address, town_or_city=town_or_city, county=county, postcode=postcode, country=country ) # create order item for each items in that particular order for item in cart: product = get_object_or_404(Book, pk=int(item['id'])) # price to be saved as base unit price price = item['price'] quantity = item['quantity_ordered'] OrderItem.objects.create(order=order, price=price, quantity=quantity, product=product) # update stock for each product product.quantity = product.quantity - quantity product.save() # send order confirmation email to user 160220 email_subject = 'Your Pick A Book\'s Order Receipt' sender_email = settings.DEFAULT_FROM_EMAIL recipient_email = [sender_email, request.user.email] # get order ID object_record = Order.objects.filter(stripe_token=stripeToken) order_id = list(object_record.values())[0]['id'] # get datetime for order date and shipping date order_date = datetime.date.today() shipping_date = order_date + datetime.timedelta(days=3) context = { 'user': request.user, 'order_total': total_amount, 'shopping_cart': cart, 'order_id': order_id, 'delivery_fee': delivery_fee, # 220220 'order_date':order_date, 'shipping_date':shipping_date, } # create and send the email html_notification_message = render_to_string('Order/order_confirmation.template.html', context) plain_message = strip_tags(html_notification_message) msg = EmailMultiAlternatives(email_subject, plain_message, sender_email, recipient_email) msg.attach_alternative(html_notification_message, "text/html") msg.send() # empty the shopping cart request.session['shopping_cart'] = {} return redirect(reverse('get_index')) else: messages.error(request, "Unable to take payment.") # errors adapted from https://github.com/justdjango/django-ecommerce/blob/master/core/views.py except stripe.error.CardError as e: body = e.json_body err = body.get('error', {}) messages.error(request, f"{err.get('message')}") return redirect(reverse('get_index')) except stripe.error.RateLimitError as e: # Too many requests made to the API too quickly messages.error(request, "Rate Limit Error") return redirect("get_index") except stripe.error.InvalidRequestError as e: # Invalid parameters were supplied to Stripe's API messages.error(request, "Ïnvalid parameters") return redirect("get_index") except stripe.error.AuthenticationError as e: # Authentication with Stripe's API failed # (maybe you changed API keys recently) messages.error(request, "Not authenticated") return redirect("get_index") except stripe.error.APIConnectionError as e: # Network communication with Stripe failed messages.error(request, "Connection error") return redirect("get_index") except stripe.error.StripeError as e: # Display a very generic error to the user, and maybe send # yourself an email messages.error(request, "Something went wrong. You were not charged. Please try again.") return redirect("get_index") except Exception as e: # Send email to ourselves print(e) messages.error(request, "An error occured. We have been notified and are currently looking into it.") return redirect("get_index") else: messages.error(request, "We were unable to take a payment with that card!") return render(request, 'Order/checkout.template.html', { 'publishable': settings.STRIPE_PUBLISHABLE_KEY, 'payment_form': payment_form, 'order_form': order_form, 'amount': total_amount }) else: order_form = OrderForm() payment_form = PaymentForm() return render(request, 'Order/checkout.template.html', { 'publishable': settings.STRIPE_PUBLISHABLE_KEY, 'payment_form': payment_form, 'order_form': order_form, 'amount': total_amount })
def sendEmailHtml(email_type, ctx, to, _group=None): """Este modulo esta en proceso de construccion, por el momento se utilizara este metodo que recibe el tipo de correo que se envia y el contexto con las variables que se trasmitiran a cada template. La siguiente lista define los valores perimitidos para la variable type y su respectivo significado. 1- Correo de validacion. (Siempre es necesario) 2- Correo de nueva reunion (Depende del grupo) 3- Correo de nueva Acta (Depende del grupo) 4- Correo de asignacion de rol (Depende del grupo) 5- Correo de confirmacion de asistencia a reunion (Depende del grupo) 6- Correo de invitacion a un grupo (Por definir) 7- Correo de invitacion a actarium (Siempre es necesario) 8- Correo de notificacion de aceptacion de grupo (Depende del grupo) 9- Correo notificacion de feedback al staff de Actarium (Siempre es necesario) 10- email_resend_activate_account (Por definir) 11- email_group_reinvitation (Depende del grupo) 12- email_new_annotation (Depende del grupo) 13- email_new_minutes_for_approvers (Depende del grupo) 14- Correo de solicitud de acceso a DNI para un grupo (Depende del grupo) 15- Recordar aprobar un acta. (va a toda la comisión) 16- Correo de invitacion a organizacion""" htmly = "" print email_type, ctx, to if email_type == 1: subject = ctx['username'] + " Bienvenido a %s" % settings.PROJECT_NAME plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_activate_account.html') elif email_type == 2: # no necesary subject = ctx['firstname'] + " (" + ctx[ 'username'] + u") Te ha invitado a una reunión del grupo " + ctx[ 'groupname'] + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_new_reunion.html') elif email_type == 3: # colocar restriccioin subject = u"El acta " + ctx[ "code"] + u" ya está disponible en el grupo " + ctx[ 'groupname'] + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_new_minutes.html') elif email_type == 4: # colocar restriccion subject = ctx['firstname'] + " (" + ctx[ 'username'] + u") te asignó como " + ctx[ 'rolename'] + " en el grupo " + ctx['groupname'] + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_set_role.html') elif email_type == 5: subject = ctx['firstname'] + " (" + ctx['username'] + ") " + ctx[ 'response'] + u" a la reunión de " + ctx['groupname'] + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_confirm_assistance.html') elif email_type == 6: # colocar restriccoin subject = ctx['full_name'] + " (" + ctx[ 'username'] + ") " + u" te invitó a unirte al grupo " + ctx[ 'groupname'] + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_group_invitation.html') elif email_type == 7: subject = ctx[ 'username'] + u" te invitó a usar %s, El espacio más cómodo para registrar el resultado de tus reuniones." % settings.PROJECT_NAME plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_actarium_invitation.html') elif email_type == 8: subject = ctx['username'] + u" " + ctx[ 'response'] + u" ha aceptado la invitación al grupo " + ctx[ 'groupname'] + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template( 'emailmodule/email_response_group_invitation.html') elif email_type == 9: subject = ctx['email'] + " Dejo un comentario tipo: " + ctx[ 'type_feed'] + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_feedback_notification.html') elif email_type == 10: subject = ctx['firstname'] + " (" + ctx[ 'username'] + ") " + u"está solicitando tu precencia" + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_resend_activate_account.html') elif email_type == 11: subject = ctx['firstname'] + " (" + ctx[ 'username'] + ") " + u"quiere que hacerte de su grupo " + ctx[ 'groupname'] + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_group_reinvitation.html') elif email_type == 12: subject = ctx['firstname'] + " (" + ctx[ 'username'] + ") " + u"publicó una anotación en un Acta del grupo " + ctx[ 'groupname'] + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_new_annotation.html') elif email_type == 13: # colocar restriccioin subject = ctx['firstname'] + " (" + ctx[ 'username'] + u") redactó el acta " + ctx[ 'code'] + " en el grupo " + ctx['groupname'] + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template( 'emailmodule/email_new_minutes_for_approvers.html') elif email_type == 14: # colocar restriccion subject = ctx['firstname'] + " (" + ctx[ 'username'] + u") Solicita acceso a tu DNI para el grupo " + ctx[ 'groupname'] + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_dni_request.html') elif email_type == 15: subject = u"El acta " + ctx['code'] + " del grupo " + ctx[ 'groupname'] + u" espera tu aprobación" + END_SUBJECT plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_remember_approve.html') elif email_type == 16: subject = ctx[ 'from_first_name'] + u" te invitó a usar %s, El espacio más cómodo para registrar el resultado de tus reuniones." % settings.PROJECT_NAME plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/email_org_invitation.html') else: plaintext = get_template('emailmodule/emailtest.txt') htmly = get_template('emailmodule/emailtest.html') subject, to = 'Mensaje de prueba', ['*****@*****.**'] from_email = '%s <*****@*****.**>' % settings.PROJECT_NAME ctx["URL_BASE"] = settings.URL_BASE # <- está en el Context proccessor y no funciona con get_template d = Context(ctx) text_content = plaintext.render(d) if htmly: html_content = htmly.render(d) else: return actives_required_list = [ 3, 4, 6, 14 ] # This list contains the number of email_type that requires the user is active in actarium if email_type in actives_required_list: to = activeFilter(to) to = groupAdminFilter(to, email_type, _group) try: smtp = settings.EMAIL_HOST_PASSWORD and settings.EMAIL_HOST_USER except NameError: smtp = None if smtp: if len(to) > 0 and not settings.DEBUG: sendGmailEmail(to, subject, html_content) else: msg = EmailMultiAlternatives(subject, text_content, from_email, to) msg.attach_alternative(html_content, "text/html") try: msg.send() except Exception, e: print e print "Error al enviar correo electronico tipo: ", email_type, " con plantilla HTML." saveErrorLog( 'Ha ocurrido un error al intentar enviar un correo de tipo %s a %s' % (email_type, to))
def get_scan_report_html_api(request, scan_id): scan = get_object_or_404(Scan.objects.for_user(request.user), id=scan_id) send_email = request.GET.get('email', None) tmp_scan = model_to_dict(scan) tmp_scan['assets'] = [] for asset in scan.assets.all(): tmp_scan['assets'].append(asset.value) tmp_scan['engine_type_name'] = scan.engine_type.name tmp_scan['engine_policy_name'] = scan.engine_policy.name findings = RawFinding.objects.filter(scan=scan.id) findings_tmp = list() for sev in ["high", "medium", "low", "info", "critical"]: tmp = RawFinding.objects.filter(scan=scan, severity=sev).order_by( 'title', 'type') if tmp.count() > 0: findings_tmp += tmp findings_by_asset = dict() for asset in scan.assets.all(): findings_by_asset_tmp = list() for sev in ["critical", "high", "medium", "low", "info"]: tmp = RawFinding.objects.filter(scan=scan, asset=asset, severity=sev).order_by( 'title', 'type') if tmp.count() > 0: findings_by_asset_tmp += tmp findings_by_asset.update({asset.value: findings_by_asset_tmp}) findings_stats = { "total": findings.count(), "high": findings.filter(severity='high').exclude( Q(status='false-positive') | Q(status='duplicate')).count(), "medium": findings.filter(severity='medium').exclude( Q(status='false-positive') | Q(status='duplicate')).count(), "low": findings.filter(severity='low').exclude( Q(status='false-positive') | Q(status='duplicate')).count(), "info": findings.filter(severity='info').count(), "critical": findings.filter(severity='critical').exclude( Q(status='false-positive') | Q(status='duplicate')).count() } for asset in scan.assets.all(): findings_stats.update({ asset.value: { "total": findings.filter(asset=asset).count(), "critical": findings.filter(asset=asset, severity='critical').exclude( Q(status='false-positive') | Q(status='duplicate')).count(), "high": findings.filter(asset=asset, severity='high').exclude( Q(status='false-positive') | Q(status='duplicate')).count(), "medium": findings.filter(asset=asset, severity='medium').exclude( Q(status='false-positive') | Q(status='duplicate')).count(), "low": findings.filter(asset=asset, severity='low').exclude( Q(status='false-positive') | Q(status='duplicate')).count(), "info": findings.filter(asset=asset, severity='info').count(), } }) report_params = { 'scan': tmp_scan, 'findings': findings_by_asset, 'findings_stats': findings_stats } if send_email is None: # Return HTML report as response return render(request, 'report-scan.html', report_params) else: # Send Email and return status as JSON response msg_text = render_to_string("email_send_report.txt") msg_html = render_to_string("email_send_report.html", report_params) html_report = render_to_string('report-scan.html', report_params) subject = '[PatrowlManager] Scan Report available - {}'.format(scan) try: recipients = Setting.objects.get(key="alerts.endpoint.email").value except Exception: logger.error( 'Unable to send report as email message. "alerts.endpoint.email" setting not configured:' ) return JsonResponse( { 'status': 'error', 'reason': '"alerts.endpoint.email" setting not configured' }, 400) try: msg = EmailMultiAlternatives(subject=subject, body=msg_text, from_email=settings.EMAIL_HOST_USER, to=[recipients]) msg.attach_alternative(msg_html, "text/html") msg.attach('scan_report.html', html_report, "text/html") msg.send() except Exception as e: logger.error('Unable to send report as email message:', e) return JsonResponse({ 'status': 'error', 'reason': '{}'.format(e) }, 400) return JsonResponse({"status": "success"}, safe=False)
def send_messages(user, action, subject, email_column, canvas_id_column, from_email, send_to_canvas, send_confirmation, track_read): """ Performs the submission of the emails for the given action and with the given subject. The subject will be evaluated also with respect to the rows, attributes, and conditions. :param user: User object that executed the action :param action: Action from where to take the messages :param subject: Email subject :param email_column: Name of the column from which to extract emails :param from_email: Email of the sender :param send_confirmation: Boolean to send confirmation to sender :param track_read: Should read tracking be included? :return: Send the emails """ # Evaluate the action string, evaluate the subject, and get the value of # the email colummn. result = evaluate_action(action, extra_string=subject, column_name=email_column) # this is for canvas inbox recipients_list = [] result_2nd = evaluate_action_canvas(action, extra_string=subject, column_name=canvas_id_column) # Check the type of the result to see if it was successful if not isinstance(result, list): # Something went wrong. The result contains a message return result track_col_name = '' data_frame = None if track_read: data_frame = pandas_db.load_from_db(action.workflow.id) # Make sure the column name does not collide with an existing one i = 0 # Suffix to rename while True: i += 1 track_col_name = 'EmailRead_{0}'.format(i) if track_col_name not in data_frame.columns: break # CC the message to canvas conversation Api if the box send_to_canvas is ticked if send_to_canvas: msgs = [] for msg_body, msg_subject, msg_to in result_2nd: # Get the plain text content and bundle it together with the HTML in # a message to be added to the list. text_content = strip_tags(msg_body) recipients_list.append(str(msg_to)) #msg.attach_alternative(msg_body + track_str, "text/html") #msgs.append(msg) try: # send a plain text copy to canvas inbox p = post_to_canvas_api() p.set_payload(True, '', '', recipients_list, msg_subject, html2text.html2text(msg_body)) r = p.post_to_conversation(p.access_token, p.payload) # extracting response text pastebin_url = r.text print(r.status_code) print(pastebin_url) except Exception as e: # Something went wrong, notify above return str(e) # Update the number of filtered rows if the action has a filter (table # might have changed) filter = action.conditions.filter(is_filter=True).first() if filter and filter.n_rows_selected != len(result): filter.n_rows_selected = len(result) filter.save() # Everything seemed to work to create the messages. msgs = [] for msg_body, msg_subject, msg_to in result: # If read tracking is on, add suffix for message (or empty) if track_read: # The track id must identify: action & user track_id = { 'action': action.id, 'sender': user.email, 'to': msg_to, 'column_to': email_column, 'column_dst': track_col_name } track_str = \ """<img src="https://{0}{1}{2}?v={3}" alt="" style="position:absolute; visibility:hidden"/>""".format( Site.objects.get_current().domain, ontask_settings.BASE_URL, reverse('trck'), signing.dumps(track_id) ) else: track_str = '' # Get the plain text content and bundle it together with the HTML in # a message to be added to the list. text_content = strip_tags(msg_body) msg = EmailMultiAlternatives(msg_subject, text_content, from_email, [msg_to]) msg.attach_alternative(msg_body + track_str, "text/html") msgs.append(msg) # Mass mail! try: connection = mail.get_connection() connection.send_messages(msgs) except Exception as e: # Something went wrong, notify above return str(e) # Add the column if needed if track_read: # Create the new column and store column = Column(name=track_col_name, workflow=action.workflow, data_type='integer', is_key=False, position=action.workflow.ncols + 1) column.save() # Increase the number of columns in the workflow action.workflow.ncols += 1 action.workflow.save() # Initial value in the data frame and store the table data_frame[track_col_name] = 0 ops.store_dataframe_in_db(data_frame, action.workflow.id) # Log the events (one per email) now = datetime.datetime.now(pytz.timezone(ontask_settings.TIME_ZONE)) context = { 'user': user.id, 'action': action.id, 'email_sent_datetime': str(now), } for msg in msgs: context['subject'] = msg.subject context['body'] = msg.body context['from_email'] = msg.from_email context['to_email'] = msg.to[0] logs.ops.put(user, 'action_email_sent', action.workflow, context) # Log the event logs.ops.put( user, 'action_email_sent', action.workflow, { 'user': user.id, 'action': action.name, 'num_messages': len(msgs), 'email_sent_datetime': str(now), 'filter_present': filter is not None, 'num_rows': action.workflow.nrows, 'subject': subject, 'from_email': user.email }) # If no confirmation email is required, done if not send_confirmation: return None # Creating the context for the personal email context = { 'user': user, 'action': action, 'num_messages': len(msgs), 'email_sent_datetime': now, 'filter_present': filter is not None, 'num_rows': action.workflow.nrows, 'num_selected': filter.n_rows_selected if filter else -1 } # Create template and render with context try: html_content = Template(str(getattr(settings, 'NOTIFICATION_TEMPLATE'))).render( Context(context)) text_content = strip_tags(html_content) except TemplateSyntaxError as e: return 'Syntax error detected in OnTask notification template (' + \ e.message + ')' # Log the event logs.ops.put( user, 'action_email_notify', action.workflow, { 'user': user.id, 'action': action.id, 'num_messages': len(msgs), 'email_sent_datetime': str(now), 'filter_present': filter is not None, 'num_rows': action.workflow.nrows, 'subject': str(getattr(settings, 'NOTIFICATION_SUBJECT')), 'body': text_content, 'from_email': str(getattr(settings, 'NOTIFICATION_SENDER')), 'to_email': [user.email] }) # Send email out try: send_mail(str(getattr(settings, 'NOTIFICATION_SUBJECT')), text_content, str(getattr(settings, 'NOTIFICATION_SENDER')), [user.email], html_message=html_content) except Exception as e: return 'An error occurred when sending your notification: ' + e.message return None
def _send_course_email(entry_id, email_id, to_list, global_email_context, subtask_status): """ Performs the email sending task. Sends an email to a list of recipients. Inputs are: * `entry_id`: id of the InstructorTask object to which progress should be recorded. * `email_id`: id of the CourseEmail model that is to be emailed. * `to_list`: list of recipients. Each is represented as a dict with the following keys: - 'profile__name': full name of User. - 'email': email address of User. - 'pk': primary key of User model. * `global_email_context`: dict containing values that are unique for this email but the same for all recipients of this email. This dict is to be used to fill in slots in email template. It does not include 'name' and 'email', which will be provided by the to_list. * `subtask_status` : object of class SubtaskStatus representing current status. Sends to all addresses contained in to_list that are not also in the Optout table. Emails are sent multi-part, in both plain text and html. Returns a tuple of two values: * First value is a SubtaskStatus object which represents current progress at the end of this call. * Second value is an exception returned by the innards of the method, indicating a fatal error. In this case, the number of recipients that were not sent have already been added to the 'failed' count above. """ # Get information from current task's request: parent_task_id = InstructorTask.objects.get(pk=entry_id).task_id task_id = subtask_status.task_id total_recipients = len(to_list) recipient_num = 0 total_recipients_successful = 0 total_recipients_failed = 0 recipients_info = Counter() log.info( "BulkEmail ==> Task: %s, SubTask: %s, EmailId: %s, TotalRecipients: %s", parent_task_id, task_id, email_id, total_recipients ) try: course_email = CourseEmail.objects.get(id=email_id) except CourseEmail.DoesNotExist as exc: log.exception( "BulkEmail ==> Task: %s, SubTask: %s, EmailId: %s, Could not find email to send.", parent_task_id, task_id, email_id ) raise # Exclude optouts (if not a retry): # Note that we don't have to do the optout logic at all if this is a retry, # because we have presumably already performed the optout logic on the first # attempt. Anyone on the to_list on a retry has already passed the filter # that existed at that time, and we don't need to keep checking for changes # in the Optout list. if subtask_status.get_retry_count() == 0: to_list, num_optout = _filter_optouts_from_recipients(to_list, course_email.course_id) subtask_status.increment(skipped=num_optout) course_title = global_email_context['course_title'] # use the email from address in the CourseEmail, if it is present, otherwise compute it from_addr = course_email.from_addr if course_email.from_addr else \ _get_source_address(course_email.course_id, course_title) # use the CourseEmailTemplate that was associated with the CourseEmail course_email_template = course_email.get_template() try: connection = get_connection() connection.open() # Define context values to use in all course emails: email_context = {'name': '', 'email': ''} email_context.update(global_email_context) while to_list: # Update context with user-specific values from the user at the end of the list. # At the end of processing this user, they will be popped off of the to_list. # That way, the to_list will always contain the recipients remaining to be emailed. # This is convenient for retries, which will need to send to those who haven't # yet been emailed, but not send to those who have already been sent to. recipient_num += 1 current_recipient = to_list[-1] email = current_recipient['email'] email_context['email'] = email email_context['name'] = current_recipient['profile__name'] email_context['user_id'] = current_recipient['pk'] email_context['course_id'] = course_email.course_id # Construct message content using templates and context: plaintext_msg = course_email_template.render_plaintext(course_email.text_message, email_context) html_msg = course_email_template.render_htmltext(course_email.html_message, email_context) # Create email: email_msg = EmailMultiAlternatives( course_email.subject, plaintext_msg, from_addr, [email], connection=connection ) email_msg.attach_alternative(html_msg, 'text/html') # Throttle if we have gotten the rate limiter. This is not very high-tech, # but if a task has been retried for rate-limiting reasons, then we sleep # for a period of time between all emails within this task. Choice of # the value depends on the number of workers that might be sending email in # parallel, and what the SES throttle rate is. if subtask_status.retried_nomax > 0: sleep(settings.BULK_EMAIL_RETRY_DELAY_BETWEEN_SENDS) try: log.info( "BulkEmail ==> Task: %s, SubTask: %s, EmailId: %s, Recipient num: %s/%s, \ Recipient name: %s, Email address: %s", parent_task_id, task_id, email_id, recipient_num, total_recipients, current_recipient['profile__name'], email ) with dog_stats_api.timer('course_email.single_send.time.overall', tags=[_statsd_tag(course_title)]): connection.send_messages([email_msg]) except SMTPDataError as exc: # According to SMTP spec, we'll retry error codes in the 4xx range. 5xx range indicates hard failure. total_recipients_failed += 1 log.error( "BulkEmail ==> Status: Failed(SMTPDataError), Task: %s, SubTask: %s, EmailId: %s, \ Recipient num: %s/%s, Email address: %s", parent_task_id, task_id, email_id, recipient_num, total_recipients, email ) if exc.smtp_code >= 400 and exc.smtp_code < 500: # This will cause the outer handler to catch the exception and retry the entire task. raise exc else: # This will fall through and not retry the message. log.warning( 'BulkEmail ==> Task: %s, SubTask: %s, EmailId: %s, Recipient num: %s/%s, \ Email not delivered to %s due to error %s', parent_task_id, task_id, email_id, recipient_num, total_recipients, email, exc.smtp_error ) dog_stats_api.increment('course_email.error', tags=[_statsd_tag(course_title)]) subtask_status.increment(failed=1) except SINGLE_EMAIL_FAILURE_ERRORS as exc: # This will fall through and not retry the message. total_recipients_failed += 1 log.error( "BulkEmail ==> Status: Failed(SINGLE_EMAIL_FAILURE_ERRORS), Task: %s, SubTask: %s, \ EmailId: %s, Recipient num: %s/%s, Email address: %s, Exception: %s", parent_task_id, task_id, email_id, recipient_num, total_recipients, email, exc ) dog_stats_api.increment('course_email.error', tags=[_statsd_tag(course_title)]) subtask_status.increment(failed=1) else: total_recipients_successful += 1 log.info( "BulkEmail ==> Status: Success, Task: %s, SubTask: %s, EmailId: %s, \ Recipient num: %s/%s, Email address: %s,", parent_task_id, task_id, email_id, recipient_num, total_recipients, email ) dog_stats_api.increment('course_email.sent', tags=[_statsd_tag(course_title)]) if settings.BULK_EMAIL_LOG_SENT_EMAILS: log.info('Email with id %s sent to %s', email_id, email) else: log.debug('Email with id %s sent to %s', email_id, email) subtask_status.increment(succeeded=1) # Pop the user that was emailed off the end of the list only once they have # successfully been processed. (That way, if there were a failure that # needed to be retried, the user is still on the list.) recipients_info[email] += 1 to_list.pop() log.info( "BulkEmail ==> Task: %s, SubTask: %s, EmailId: %s, Total Successful Recipients: %s/%s, \ Failed Recipients: %s/%s", parent_task_id, task_id, email_id, total_recipients_successful, total_recipients, total_recipients_failed, total_recipients ) duplicate_recipients = ["{0} ({1})".format(email, repetition) for email, repetition in recipients_info.most_common() if repetition > 1] if duplicate_recipients: log.info( "BulkEmail ==> Task: %s, SubTask: %s, EmailId: %s, Total Duplicate Recipients [%s]: [%s]", parent_task_id, task_id, email_id, len(duplicate_recipients), ', '.join(duplicate_recipients) ) except INFINITE_RETRY_ERRORS as exc: dog_stats_api.increment('course_email.infinite_retry', tags=[_statsd_tag(course_title)]) # Increment the "retried_nomax" counter, update other counters with progress to date, # and set the state to RETRY: subtask_status.increment(retried_nomax=1, state=RETRY) return _submit_for_retry( entry_id, email_id, to_list, global_email_context, exc, subtask_status, skip_retry_max=True ) except LIMITED_RETRY_ERRORS as exc: # Errors caught here cause the email to be retried. The entire task is actually retried # without popping the current recipient off of the existing list. # Errors caught are those that indicate a temporary condition that might succeed on retry. dog_stats_api.increment('course_email.limited_retry', tags=[_statsd_tag(course_title)]) # Increment the "retried_withmax" counter, update other counters with progress to date, # and set the state to RETRY: subtask_status.increment(retried_withmax=1, state=RETRY) return _submit_for_retry( entry_id, email_id, to_list, global_email_context, exc, subtask_status, skip_retry_max=False ) except BULK_EMAIL_FAILURE_ERRORS as exc: dog_stats_api.increment('course_email.error', tags=[_statsd_tag(course_title)]) num_pending = len(to_list) log.exception(('Task %s: email with id %d caused send_course_email task to fail ' 'with "fatal" exception. %d emails unsent.'), task_id, email_id, num_pending) # Update counters with progress to date, counting unsent emails as failures, # and set the state to FAILURE: subtask_status.increment(failed=num_pending, state=FAILURE) return subtask_status, exc except Exception as exc: # pylint: disable=broad-except # Errors caught here cause the email to be retried. The entire task is actually retried # without popping the current recipient off of the existing list. # These are unexpected errors. Since they might be due to a temporary condition that might # succeed on retry, we give them a retry. dog_stats_api.increment('course_email.limited_retry', tags=[_statsd_tag(course_title)]) log.exception(('Task %s: email with id %d caused send_course_email task to fail ' 'with unexpected exception. Generating retry.'), task_id, email_id) # Increment the "retried_withmax" counter, update other counters with progress to date, # and set the state to RETRY: subtask_status.increment(retried_withmax=1, state=RETRY) return _submit_for_retry( entry_id, email_id, to_list, global_email_context, exc, subtask_status, skip_retry_max=False ) else: # All went well. Update counters with progress to date, # and set the state to SUCCESS: subtask_status.increment(state=SUCCESS) # Successful completion is marked by an exception value of None. return subtask_status, None finally: # Clean up at the end. connection.close()
def build_email( template_prefix: str, to_user_ids: Optional[List[int]] = None, to_emails: Optional[List[str]] = None, from_name: Optional[str] = None, from_address: Optional[str] = None, reply_to_email: Optional[str] = None, language: Optional[str] = None, context: Mapping[str, Any] = {}, realm: Optional[Realm] = None, ) -> EmailMultiAlternatives: # Callers should pass exactly one of to_user_id and to_email. assert (to_user_ids is None) ^ (to_emails is None) if to_user_ids is not None: to_users = [ get_user_profile_by_id(to_user_id) for to_user_id in to_user_ids ] if realm is None: assert len({to_user.realm_id for to_user in to_users}) == 1 realm = to_users[0].realm to_emails = [ str( Address(display_name=to_user.full_name, addr_spec=to_user.delivery_email)) for to_user in to_users ] extra_headers = {} if realm is not None: # formaddr is meant for formatting (display_name, email_address) pair for headers like "To", # but we can use its utility for formatting the List-Id header, as it follows the same format, # except having just a domain instead of an email address. extra_headers["List-Id"] = formataddr((realm.name, realm.host)) context = { **context, "support_email": FromAddress.SUPPORT, "email_images_base_uri": settings.ROOT_DOMAIN_URI + "/static/images/emails", "physical_address": settings.PHYSICAL_ADDRESS, } def render_templates() -> Tuple[str, str, str]: email_subject = (loader.render_to_string( template_prefix + ".subject.txt", context=context, using="Jinja2_plaintext").strip().replace("\n", "")) message = loader.render_to_string(template_prefix + ".txt", context=context, using="Jinja2_plaintext") try: html_message = loader.render_to_string(template_prefix + ".html", context) except TemplateDoesNotExist: emails_dir = os.path.dirname(template_prefix) template = os.path.basename(template_prefix) compiled_template_prefix = os.path.join(emails_dir, "compiled", template) html_message = loader.render_to_string( compiled_template_prefix + ".html", context) return (html_message, message, email_subject) # The i18n story for emails is a bit complicated. For emails # going to a single user, we want to use the language that user # has configured for their Zulip account. For emails going to # multiple users or to email addresses without a known Zulip # account (E.g. invitations), we want to use the default language # configured for the Zulip organization. # # See our i18n documentation for some high-level details: # https://zulip.readthedocs.io/en/latest/translating/internationalization.html if not language and to_user_ids is not None: language = to_users[0].default_language if language: with override_language(language): # Make sure that we render the email using the target's native language (html_message, message, email_subject) = render_templates() else: (html_message, message, email_subject) = render_templates() logger.warning("Missing language for email template '%s'", template_prefix) if from_name is None: from_name = "Zulip" if from_address is None: from_address = FromAddress.NOREPLY if from_address == FromAddress.tokenized_no_reply_placeholder: from_address = FromAddress.tokenized_no_reply_address() if from_address == FromAddress.no_reply_placeholder: from_address = FromAddress.NOREPLY if from_address == FromAddress.support_placeholder: from_address = FromAddress.SUPPORT from_email = str(Address(display_name=from_name, addr_spec=from_address)) reply_to = None if reply_to_email is not None: reply_to = [reply_to_email] # Remove the from_name in the reply-to for noreply emails, so that users # see "noreply@..." rather than "Zulip" or whatever the from_name is # when they reply in their email client. elif from_address == FromAddress.NOREPLY: reply_to = [FromAddress.NOREPLY] mail = EmailMultiAlternatives(email_subject, message, from_email, to_emails, reply_to=reply_to, headers=extra_headers) if html_message is not None: mail.attach_alternative(html_message, "text/html") return mail
def run(self): msg = EmailMultiAlternatives(self.subject, self.text_content, self.sender_email, self.recipient_list) if self.html: msg.attach_alternative(self.html_content, self.html) msg.send()
def send_now(users, label, extra_context=None, on_site=True, sender=None, from_email=None, reply_to=None, send_if_inactive=False, _force_now=False): """ Creates a new notice. This is intended to be how other apps create new notices. notification.send(user, "friends_invite_sent", { "spam": "eggs", "foo": "bar", ) You can pass in on_site=False to prevent the notice emitted from being displayed on the site. """ if USE_CELERY and not _force_now: SendNowTask.delay(users, label, extra_context=extra_context, on_site=on_site, sender=sender, from_email=from_email, reply_to=reply_to, send_if_inactive=send_if_inactive) return if extra_context is None: extra_context = {} from_email = from_email or settings.DEFAULT_FROM_EMAIL notice_type = NoticeType.objects.get(label=label) protocol = getattr(settings, "DEFAULT_HTTP_PROTOCOL", "http") current_site = Site.objects.get_current() notices_url = u"%s://%s%s" % ( protocol, unicode(current_site), reverse("notification_notices"), ) current_language = get_language() formats = ( 'short.txt', 'short.html', 'full.txt', 'full.html', ) # TODO make formats configurable notices=[] for user in users: recipients = [] # get user language for user from language store defined in # NOTIFICATION_LANGUAGE_MODULE setting try: language = get_notification_language(user) except LanguageStoreNotAvailable: language = None if language is not None: # activate the user's language activate(language) #if html title is not present use title if extra_context.get("title", False): extra_context['title_html'] = extra_context.get('title','') # update context with user specific translations context = Context({ 'MEDIA_URL':settings.MEDIA_URL, "recipient": user, "sender": sender, "notice": ugettext(notice_type.display), "notices_url": notices_url, "current_site": current_site, }) context.update(extra_context) # get prerendered format messages messages = get_formatted_messages(formats, label, context) # Strip newlines from subject subject = ''.join(render_to_string(EMAIL_SUBJECT_TEMPLATE, { 'message': messages['short.txt'], }, context).splitlines()) body = render_to_string(EMAIL_BODY_PLAIN_TEMPLATE, { 'message': messages['full.txt'], }, context) email_body = render_to_string(EMAIL_BODY_HTML_TEMPLATE, { 'message': messages['full.html'], }, context) notice = Notice.objects.create(recipient=user, message=messages['full.html'], message_header=messages['short.html'], notice_type=notice_type, on_site=on_site, sender=sender) notices.append(notice) if should_send(user, notice_type, "1") and user.email and (send_if_inactive or user.is_active): # Email recipients.append(user.email) _email_headers = {} if reply_to: _email_headers['Reply-To'] = unicode(reply_to) if send_html_mail and email_body: _email_message = EmailMultiAlternatives(subject, body, from_email, recipients, headers=_email_headers) _email_message.attach_alternative(email_body, 'text/html') else: _email_message = EmailMessage(subject, body, from_email, recipients, headers=_email_headers) _email_message.send() # reset environment to original language activate(current_language) return notices
def drop_ride(request, ride_id): user = request.user init_User(user.username) ride = Rides.objects.get(pk=ride_id) rider = Users.objects.get(netid=user.username) idnum = str(ride.id) context = { 'start': ride.get_start_destination_display(), 'end': ride.get_end_destination_display(), 'time': ride.date_time, 'netid': user.username, } if rider.pools.filter(pk=ride_id).exists(): rider = Users.objects.get(netid=user.username) ride.usrs.remove(rider) if (ride.usrs.count() > 0): ride.seats += 1 rider.pools.remove(ride) ride.save() rider.save() # list of all the riders riders_emails = [] riders_firstnames = "" riders_fullnames = "" for rider in ride.usrs.all(): riders_emails.append(rider.netid + '@princeton.edu') riders_firstnames = riders_firstnames + ", " + rider.first_name riders_fullnames = riders_fullnames + rider.first_name + " " + rider.last_name + ', ' riders_firstnames = riders_firstnames.lstrip(', ') # put 'and' and delete comma if only two riders split_firsts = riders_firstnames.split(', ') num_riders = len(split_firsts) if num_riders == 2: riders_firstnames = (' and ').join(split_firsts) elif num_riders > 2: riders_firstnames = (', ').join(split_firsts[0:(num_riders - 1)]) riders_firstnames = riders_firstnames + ', and ' + split_firsts[num_riders - 1] riders_fullnames = riders_fullnames.rstrip(', ') # email to dropper date_obj_str = ride.date_time.strftime('%m/%d/%Y %I:%M %p')[0:date_length] time_obj_str = ride.date_time.strftime('%m/%d/%Y %I:%M %p')[date_length:] + ' EST' mail_to_dropper= EmailMultiAlternatives( subject= 'Ride #' + str(ride.id) + ' To ' + ride.get_end_destination_display(), body= 'Idk what goes here?', from_email= 'Princeton Go <*****@*****.**>', to=[user.username + '@princeton.edu'] ) # Add template mail_to_dropper.template_id = '4f75a67a-64a9-47f5-9a59-07646a578b9f' # Replace substitutions in template message = 'You have dropped a ride. For your records, below you can find the ride information.' theUser = Users.objects.get(netid=user.username) closing = 'Thank you for using Princeton Go!' mail_to_dropper.substitutions = {'%names%': theUser.first_name, '%body%': message, '%date%': date_obj_str, '%time%': time_obj_str, '%destination%': ride.get_start_destination_display() + ' to ' + ride.get_end_destination_display(), '%riders%': riders_fullnames, '%seats%': ride.seats, '%closing%': closing} mail_to_dropper.attach_alternative( "<p>This is a simple HTML email body</p>", "text/html" #don't know what this does but it doesn't work w/o it, don't delete ) mail_to_dropper.send() # email to everyone in the ride mail_to_riders = EmailMultiAlternatives( subject= 'Ride #' + str(ride.id) + ' To ' + ride.get_end_destination_display(), body= 'Idk what goes here?', from_email= 'Princeton Go <*****@*****.**>', to=riders_emails ) # Add template mail_to_riders.template_id = '4f75a67a-64a9-47f5-9a59-07646a578b9f' # Replace substitutions in template message = theUser.first_name + ' ' + theUser.last_name +' has dropped your ride. We have increased the number of available seats, as you can see below in the ride information.' closing = 'Thank you for using Princeton Go! We hope you enjoy your ride.' mail_to_riders.substitutions = {'%names%': riders_firstnames, '%body%': message, '%date%': date_obj_str, '%time%': time_obj_str, '%destination%': ride.get_start_destination_display() + ' to ' + ride.get_end_destination_display(), '%riders%': riders_fullnames, '%seats%': ride.seats, '%closing%': closing} mail_to_riders.attach_alternative( "<p>This is a simple HTML email body</p>", "text/html" #don't know what this does but it doesn't work w/o it, don't delete ) mail_to_riders.send() #make sure this is the last thing done in the view if (ride.usrs.count() == 0): ride.delete() return render(request, 'app/drop_ride.html', context)
def send(self, sender, to, subject, plain=None, html=None, cc=None, bcc=None, attach=None, replyto=None): """ Send the message. If we have PLAIN and HTML versions, send a multipart alternative MIME message, else send whichever we do have. If we have neither, raise NoContentError Arguments: - `sender`: str - `to`: list - `subject`: str - `plain`: str - `html`: str - `attach`: str or iterable of str - `replyto`: str Return: None Exceptions: NoContentError """ headers = {} if attach: raise NotImplementedError( 'Attachments not implemented for Django yet!') if replyto: headers['Reply-To'] = replyto self.sanity_check(sender, to, subject, plain=plain, html=html, cc=cc, bcc=bcc) if not cc: cc = [] if not bcc: bcc = [] # This comes straight from the docs at # https://docs.djangoproject.com/en/dev/topics/email/ from django.core.mail import EmailMultiAlternatives if not plain: plain = '' msg = EmailMultiAlternatives(u(subject), u(plain), u(sender), _stringlist(to), bcc=bcc, cc=cc, headers=headers) if html: msg.attach_alternative(ensure_unicode(html), "text/html") msg.send() return
def confirm_join_ride(request, ride_id): user = request.user ride = get_object_or_404(Rides, pk=ride_id) rider = Users.objects.get(netid=user.username) context = { 'Riders': ride.usrs.all(), 'title': 'Successfully Joined Ride', 'start': ride.start_destination, 'dest': ride.get_end_destination_display(), 'date': ride.date_time, 'netid': user.username, 'rtype': request.path.split('/')[1], } if not rider.pools.filter(pk=ride_id).exists(): name = "netid"+str(ride_id) init_User(user.username) rider.save() rider.pools.add(ride) rider.save() ride.usrs.add(rider) ride.seats -= 1 ride.save() # email to everyone in the ride # list of all the riders riders_emails = [] riders_firstnames = "" riders_fullnames = "" for rider in ride.usrs.all(): riders_emails.append(rider.netid + '@princeton.edu') riders_firstnames = riders_firstnames + ", " + rider.first_name riders_fullnames = riders_fullnames + rider.first_name + " " + rider.last_name + ', ' riders_firstnames = riders_firstnames.lstrip(', ') # put 'and' and delete comma if only two riders split_firsts = riders_firstnames.split(', ') num_riders = len(split_firsts) if num_riders == 2: riders_firstnames = (' and ').join(split_firsts) else: riders_firstnames = (', ').join(split_firsts[0:(num_riders - 1)]) riders_firstnames = riders_firstnames + ', and ' + split_firsts[num_riders - 1] riders_fullnames = riders_fullnames.rstrip(', ') date_obj_str = ride.date_time.strftime('%m/%d/%Y %I:%M %p')[0:date_length] time_obj_str = ride.date_time.strftime('%m/%d/%Y %I:%M %p')[date_length:] + ' EST' mail_to_riders = EmailMultiAlternatives( subject= 'Ride #' + str(ride.id) + ' To ' + ride.get_end_destination_display(), body= 'Idk what goes here?', from_email= 'Princeton Go <*****@*****.**>', to=riders_emails ) # Add template mail_to_riders.template_id = '4f75a67a-64a9-47f5-9a59-07646a578b9f' # Replace substitutions in template theUser = Users.objects.get(netid=user.username) message = theUser.first_name + ' ' + theUser.last_name +' has joined your ride! Below you can find the information for this ride, and you can coordinate how to get to your destination.' closing = 'Thank you for using Princeton Go! We hope you enjoy your ride.' mail_to_riders.substitutions = {'%names%': riders_firstnames, '%body%': message, '%date%': date_obj_str, '%time%': time_obj_str, '%destination%': ride.get_start_destination_display() + ' to ' + ride.get_end_destination_display(), '%riders%': riders_fullnames, '%seats%': ride.seats, '%closing%': closing} mail_to_riders.attach_alternative( "<p>This is a simple HTML email body</p>", "text/html" #don't know what this does but it doesn't work w/o it, don't delete ) mail_to_riders.send() return render(request, 'app/confirmed_join.html', context)
def send_stage_email(task, email_conf, token=None): if not email_conf: return text_template = loader.get_template(email_conf['template'], using='include_etc_templates') html_template = email_conf.get('html_template', None) if html_template: html_template = loader.get_template(html_template, using='include_etc_templates') emails = set() actions = {} # find our set of emails and actions that require email for action in task.actions: act = action.get_action() email = act.get_email() if email: emails.add(email) actions[str(act)] = act if not emails: return if len(emails) > 1: notes = { 'errors': (("Error: Unable to send token, More than one email for" + " task: %s") % task.uuid) } create_notification(task, notes, error=True) return context = {'task': task, 'actions': actions} if token: context.update({ 'tokenurl': settings.TOKEN_SUBMISSION_URL, 'token': token.token }) try: message = text_template.render(context) # from_email is the return-path and is distinct from the # message headers from_email = email_conf.get('from') if not from_email: from_email = email_conf['reply'] elif "%(task_uuid)s" in from_email: from_email = from_email % {'task_uuid': task.uuid} # these are the message headers which will be visible to # the email client. headers = { 'X-Adjutant-Task-UUID': task.uuid, # From needs to be set to be disctinct from return-path 'From': email_conf['reply'], 'Reply-To': email_conf['reply'], } email = EmailMultiAlternatives( email_conf['subject'], message, from_email, [emails.pop()], headers=headers, ) if html_template: email.attach_alternative(html_template.render(context), "text/html") email.send(fail_silently=False) except SMTPException as e: notes = { 'errors': ("Error: '%s' while emailing token for task: %s" % (e, task.uuid)) } errors_conf = settings.TASK_SETTINGS.get( task.task_type, settings.DEFAULT_TASK_SETTINGS).get('errors', {}).get("SMTPException", {}) if errors_conf: notification = create_notification(task, notes, error=True, engines=errors_conf.get( 'engines', True)) if errors_conf.get('notification') == "acknowledge": notification.acknowledged = True notification.save() else: create_notification(task, notes, error=True)