def sendmail(template, to, subject, headers=None, **kwargs): """ Sends an email with the selected html template. html templates can be found inside the broadguage/templates directory. Params: ======= template: str Link to the html file to be used as template. The html file is parsed by Jinja Templating before sending to the recipient. Keyword Args: ============= to: str Recipient's email sub: str Subject of the mail P.S: Other keywords are sent to Jinja Templating Language for direct parsing, as it is. Example: >>> from sendmail import sendmail >>> sendmail("emails/trainers/welcome.html",to=..."some_email.com", sub="Hey Friend!", variable1=var, variable2=var2) Email sent to some_email.com """ if not web.config.get('smtp_server'): # TODO: log warn message return html = render_template(template, **kwargs) # inline CSS to make mail clients happy html = pynliner.fromString(html) envelope = Envelope( from_addr=web.config.from_address, to_addr=to, subject=subject, html_body=html, headers=headers ) server = web.config.smtp_server port = int(web.config.get('smtp_port', 25)) username = web.config.smtp_username password = web.config.get('smtp_password') tls = web.config.get('smtp_starttls', False) result = envelope.send( host=server, port=port, login=username, password=password, tls=tls) return result
def saveFiles(): from app import updateDB, app, matches if matches: matches = matches['matches'] print matches updateDB() freezer = Freezer(app) # Create static html files freezer.freeze() with open('build/index.html','r') as html: output = fromString(html.read()) with open('build/send.html','w') as send_file: send_file.write(output) with open('build/send.txt','wb') as f: keys = matches[0].keys() dict_writer = csv.DictWriter(f, keys) dict_writer.writeheader() dict_writer.writerows(matches) return True else: print 'Looks like something wrong with date in initial URL, nothing saved' return False
def _render_email(template_name, data): rendered = _templates[template_name].render(data=data) # CSS in email HTML must be inline rendered = pynliner.fromString(rendered) return rendered
def render_mail(data): ''' Will throw exception if data does not match expected structure (that is, if the template rendering fails). ''' template_filename = 'psi_mail_host_stats.mako' template_lookup = TemplateLookup( directories=[os.path.dirname(os.path.abspath(__file__))]) # SECURITY IMPORTANT: `'h'` in the `default_filters` list causes HTML # escaping to be applied to all expression tags (${...}) in this # template. Because we're output untrusted user-supplied data, this is # essential. template = Template(filename=template_filename, default_filters=['unicode', 'h'], lookup=template_lookup) try: rendered = template.render(data=data) except: raise Exception(exceptions.text_error_template().render()) # CSS in email HTML must be inline rendered = pynliner.fromString(rendered) return rendered
def convert_one(part, config, charset): text = part.get_payload(decode=True) if part.get_charset(): charset = get_charset_from_message_fragment(part) if not isinstance(text, six.text_type): # decode=True only decodes the base64/uuencoded nature, and # will always return bytes; gotta decode it if charset is not None: text = text.decode(charset) else: try: text = text.decode('ascii') except UnicodeError: # this is because of message.py:278 and seems like a hack text = text.decode('raw-unicode-escape') if not text.startswith('!m'): return None text = re.sub(r'\s*!m\s*', '', text, re.M) if '\n-- \n' in text: pre_signature, signature = text.split('\n-- \n') md = markdown.markdown(pre_signature, output_format="html5") md += '\n<div class="signature" style="font-size: small"><p>-- <br />' md += '<br />'.join(signature.split('\n')) md += '</p></div>' else: md = markdown.markdown(text) if config.css: md = '<style>' + config.css + '</style>' + md md = pynliner.fromString(md) message = MIMEText(md, 'html', _charset="UTF-8") return message
def notify_members(self, group, event, fail_silently=True): project = group.project interface_list = [] for interface in event.interfaces.itervalues(): body = interface.to_string(event) if not body: continue interface_list.append((interface.get_title(), body)) subject = '[%s] %s: %s' % (project.name, event.get_level_display().upper(), event.message) link = '%s/%d/group/%d/' % (settings.URL_PREFIX, group.project_id, group.id) body = render_to_string('sentry/emails/error.txt', { 'group': group, 'event': event, 'link': link, 'interfaces': interface_list, }) html_body = pynliner.fromString(render_to_string('sentry/emails/error.html', { 'group': group, 'event': event, 'link': link, 'interfaces': interface_list, })) self._send_mail( subject=subject, body=body, html_body=html_body, project=project, fail_silently=fail_silently, )
def inlineStyle(file): with open(file, 'rb') as f: body = f.read() output = pynliner.fromString(body) inline_file = open('report/inline_file', 'w') inline_file.write(output) inline_file.close()
def handle(self, **options): translation.activate('ru') if 'test_users' in options and options['test_users']: users_query = User.objects.filter(id__in=options['test_users']) else: users_query = User.objects.filter( realtors__agency__in=Agency.objects.filter( realtors__user__ads__is_published=True), realtors__is_admin=True, realtors__is_active=True, is_active=True, email__gt='', subscribe_info=True, ).order_by('id') if options['start_from_user']: users_query = users_query.filter( id__gte=options['start_from_user']) for user in users_query: print 'user #%d' % user.id content = render_to_string( 'mail/mailing/mail_about_professionals.jinja.html', {}) content_with_inline_css = pynliner.fromString(content) message = EmailMessage(u'Уведомление от Mesto.UA', content_with_inline_css, settings.DEFAULT_FROM_EMAIL, [user.email]) message.content_subtype = 'html' message.send()
def format(data): ''' Will throw exception if data does not match expected structure (that is, if the template rendering fails). ''' # The values in `data` come directly from the user, so we shouldn't trust # them enough to put them directly in to a filename. platform = 'windows' if data['Metadata']['platform'] == 'windows' else 'android' version = int(data['Metadata']['version']) template_filename = 'templates/template_%s_%d.mako' % (platform, version) if template_filename not in _cached_templates: template_lookup = TemplateLookup(directories=['.']) # SECURITY IMPORTANT: `'h'` in the `default_filters` list causes HTML # escaping to be applied to all expression tags (${...}) in this # template. Because we're output untrusted user-supplied data, this is # essential. _cached_templates[template_filename] = Template(filename=template_filename, default_filters=['unicode', 'h'], lookup=template_lookup) try: rendered = _cached_templates[template_filename].render(data=data) except: raise Exception(exceptions.text_error_template().render()) # CSS in email HTML must be inline rendered = pynliner.fromString(rendered) return rendered
def convert_one(part, config): try: text = part.get_payload(None, True) if text.startswith('!m'): converter = convert_markdown elif text.startswith('!p'): converter = convert_preformat else: return None text = re.sub('\s*![pm]\s*', '', text, count=1, flags=re.M) if config.remove_sigil: part.set_payload(text) if config.utf8: text = unicode(text, 'utf8') if '\n-- \n' in text: pre_signature, signature = text.split('\n-- \n') md = converter(pre_signature, config) md += '\n<div class="signature" style="font-size: small"><p>-- <br />' md += '<br />'.join(signature.split('\n')) md += '</p></div>' else: md = converter(text, config) if config.css: md = '<style>\n' + config.css + '</style>\n' + '<body>\n' + md + '\n</body>\n' md = pynliner.fromString(md) if config.utf8: message = MIMEText(md.encode('utf-8'), 'html', _charset='utf-8') else: message = MIMEText(md, 'html') return message except Exception as e: sys.stderr.write('muttdown: ' + str(e)) return None
def handle(self, **options): if 'test_users' in options and options['test_users']: users_query = User.objects.filter(id__in=options['test_users']) else: users_query = User.objects.filter( realtors__is_active=True, last_action__gt='2016-02-28', email__gt='', subscribe_news=True).distinct().order_by('id') if options['start_from_user']: users_query = users_query.filter( id__gte=options['start_from_user']) print 'Total users: ', users_query.count() utm = make_utm_dict(utm_campaign='valion') for user in users_query: print 'user #%d' % user.id translation.activate(user.language) template = 'mail/mailing/valion_franchise.jinja.html' subject = u'Франшиза для частных риэлторов от Valion' content = render_to_string( template, { 'utm': utm, 'ga_pixel': make_ga_pixel_dict(user, utm) }) content_with_inline_css = pynliner.fromString(content) message = EmailMessage(subject, content_with_inline_css, settings.DEFAULT_FROM_EMAIL, [user.email]) message.content_subtype = 'html' message.send()
def handle(self, **options): translation.activate('ru') if 'test_users' in options and options['test_users']: users_query = User.objects.filter(id__in=options['test_users']) else: users_query = User.objects.filter( subscribe_info=True, is_active=True, email__gt='', transactions__type__in=[3, 32], transactions__time__gt=datetime.datetime( 2016, 4, 1)).distinct().order_by('id') if options['start_from_user']: users_query = users_query.filter( id__gte=options['start_from_user']) content = render_to_string('mail/mailing/mail_about_money.jinja.html', {}) content_with_inline_css = pynliner.fromString(content) for user in users_query: print 'user #%d' % user.id message = EmailMessage(u'Ваши деньги на балансе в Личном кабинете', content_with_inline_css, settings.DEFAULT_FROM_EMAIL, to=[user.email]) message.content_subtype = 'html' message.send()
def handle(self, **options): translation.activate('ru') last_action_time = datetime.datetime.now() - datetime.timedelta( days=31) if 'test_users' in options and options['test_users']: users_query = User.objects.filter(id__in=options['test_users']) else: user_ids = set( Ad.objects.filter(deal_type='newhomes', is_published=True).values_list('user_id', flat=True)) users_query = User.objects.filter(id__in=user_ids, email__gt='') if options['start_from_user']: users_query = users_query.filter( id__gte=options['start_from_user']) for user in users_query: print 'user #%d' % user.id content = render_to_string( 'mail/mailing/mail_about_newhomes_area.jinja.html', {}) content_with_inline_css = pynliner.fromString(content) message = EmailMessage(u'Уведомление от Mesto.UA', content_with_inline_css, settings.DEFAULT_FROM_EMAIL, [user.email]) message.content_subtype = 'html' message.send()
def send_mail(template_prefix, from_email, recipient_list, template_context, fail_silently=False, **kwargs): # Sends a templated HTML email. # # Unrecognized arguments are passed on to Django's EmailMultiAlternatives's init method. # add default template context variables from settings.DEFAULT_TEMPLATE_CONTEXT template_context = build_template_context(template_context) # subject subject = render_to_string(template_prefix + '_subject.txt', template_context) subject = ''.join(subject.splitlines()) # remove superfluous line breaks # Add subject as a new context variable, and it is used in the base HTML template's title tag. template_context['subject'] = subject # body text_body = render_to_string(template_prefix + '.txt', template_context) html_body = render_to_string(template_prefix + '.html', template_context) # inline HTML styles because some mail clients dont process the <style> tag html_body = pynliner.fromString(html_body) # construct MIME message msg = EmailMultiAlternatives( subject=subject, body=text_body, from_email=from_email, to=recipient_list, **kwargs ) msg.attach_alternative(html_body, "text/html") # send! msg.send(fail_silently=fail_silently)
def with_inline_css(html_without_css): """Returns html with inline css if the css file path exists else returns html with out the inline css. """ css_filepath = settings.NOTIFICATION_EMAIL_CSS if not css_filepath.startswith('/'): css_filepath = file_path_finder(settings.NOTIFICATION_EMAIL_CSS) if css_filepath: with open(css_filepath, "r") as _file: css_content = _file.read() # pynliner imports cssutils, which has an expensive initialization. All # told, it can account for 15-20% of "fast" LMS startup (without asset # compilation). So we're going to load it locally here so that we delay # that one-time hit until we actually do the (rare) operation that is # sending a credit notification email. import pynliner # insert style tag in the html and run pyliner. html_with_inline_css = pynliner.fromString( HTML('<style>{}</style>{}').format(css_content, html_without_css)) return html_with_inline_css return html_without_css
def handle(self, *args, **options): start_time_range = (datetime.datetime.now() - datetime.timedelta(days=6), datetime.datetime.now() - datetime.timedelta(days=5)) users = User.objects.filter(user_plans__is_active=True, user_plans__ads_limit__gt=0, user_plans__start__range=start_time_range, ads_count=0, subscribe_info=True, email__gt='').distinct().order_by('id') print '--> Start to send notification', datetime.datetime.now() utm = make_utm_dict(utm_campaign='plan_notification') for user in users: print ' --> user #%d' % user.id translation.activate(user.language) content = render_to_string( 'paid_services/mail/plan-notification.jinja.html', { 'utm': utm, 'ga_pixel': make_ga_pixel_dict(user, utm), 'plan': user.get_active_plan() }) content_with_inline_css = pynliner.fromString(content) message = EmailMessage(_('Активируйте свои объявления'), content_with_inline_css, settings.DEFAULT_FROM_EMAIL, [user.email]) message.content_subtype = 'html' message.send() print '--> Finish to send notification', datetime.datetime.now()
def convert_one(part, config): try: text = part.get_payload(decode=True) if not isinstance(text, six.text_type): # no, I don't know why decode=True sometimes fails to decode. text = text.decode('utf-8') if not text.startswith('!m'): return None text = re.sub('\s*!m\s*', '', text, re.M) if '\n-- \n' in text: pre_signature, signature = text.split('\n-- \n') md = markdown.markdown(pre_signature, output_format="html5") md += '\n<div class="signature" style="font-size: small"><p>-- <br />' md += '<br />'.join(signature.split('\n')) md += '</p></div>' else: md = markdown.markdown(text) if config.css: md = '<style>' + config.css + '</style>' + md md = pynliner.fromString(md) message = MIMEText(md, 'html', _charset="UTF-8") return message except Exception: raise return None
def handle(self, *args, **options): script_start = time.time() start_at = datetime.datetime.now() - datetime.timedelta(days=1) users = WebinarReminder.objects.filter( webinar__type='webinar', webinar__start_at__gt=start_at, webinar__finish_at__lte=datetime.datetime.now()).select_related( 'webinar') for user in users: translation.activate(user.language) subject = _(u'Запись вебинара %s' % user.webinar.get_title()) content = render_to_string( 'mail/webinars/after_webinar_notification_{:s}.jinja.html'. format(user.language), { 'user': user, 'webinar': user.webinar }) content_with_inline_css = pynliner.fromString(content) message = EmailMessage(subject, content_with_inline_css, settings.DEFAULT_FROM_EMAIL, [user.email]) message.content_subtype = 'html' message.send() print 'Sending email (%s) was successful' % user.email print '%.2f sec' % (time.time() - script_start)
def render_mail(data): ''' Will throw exception if data does not match expected structure (that is, if the template rendering fails). ''' template_filename = 'psi_mail_stats.mako' template_lookup = TemplateLookup(directories=[os.path.dirname(os.path.abspath(__file__))]) # SECURITY IMPORTANT: `'h'` in the `default_filters` list causes HTML # escaping to be applied to all expression tags (${...}) in this # template. Because we're output untrusted user-supplied data, this is # essential. template = Template(filename=template_filename, default_filters=['unicode', 'h'], lookup=template_lookup) try: rendered = template.render(data=data) except: raise Exception(exceptions.text_error_template().render()) # CSS in email HTML must be inline rendered = pynliner.fromString(rendered) return rendered
def format(data): ''' Will throw exception if data does not match expected structure (that is, if the template rendering fails). ''' # The values in `data` come directly from the user, so we shouldn't trust # them enough to put them directly in to a filename. platform = 'windows' if data['Metadata'][ 'platform'] == 'windows' else 'android' version = int(data['Metadata']['version']) template_filename = 'templates/template_%s_%d.mako' % (platform, version) if template_filename not in _cached_templates: template_lookup = TemplateLookup(directories=['.']) # SECURITY IMPORTANT: `'h'` in the `default_filters` list causes HTML # escaping to be applied to all expression tags (${...}) in this # template. Because we're output untrusted user-supplied data, this is # essential. _cached_templates[template_filename] = Template( filename=template_filename, default_filters=['unicode', 'h'], lookup=template_lookup) try: rendered = _cached_templates[template_filename].render(data=data) except: raise Exception(exceptions.text_error_template().render()) # CSS in email HTML must be inline rendered = pynliner.fromString(rendered) return rendered
def _send(recipient_pks, recipient_emails, template_path, context, from_email, fail_silently): recipients = list(User.objects.filter(pk__in=recipient_pks)) recipients += recipient_emails current_language = get_language() current_site = Site.objects.get(id=settings.SITE_ID) default_context = context or {} default_context["current_site"] = current_site default_context["STATIC_URL"] = settings.STATIC_URL subject_path = "%s/short.txt" % template_path text_path = "%s/email.txt" % template_path html_path = "%s/email.html" % template_path for recipient in recipients: # if it is user, get the email and switch the language if isinstance(recipient, User): email = recipient.email try: language = get_users_language(recipient) except LanguageStoreNotAvailable: language = None if language is not None: # activate the user's language activate(language) else: email = recipient # populate per-recipient context context = Context(default_context) context['recipient'] = recipient context['email'] = email # load email subject, strip and remove line breaks subject = render_to_string(subject_path, context).strip() subject = "".join(subject.splitlines()) # this must be a single line text = render_to_string(text_path, context) msg = EmailMultiAlternatives(subject, text, from_email, [email]) # try to attach the html variant try: body = render_to_string(html_path, context) if getattr(settings, "TEMPLATEDEMAILS_USE_PYNLINER", False): import pynliner body = pynliner.fromString(body) msg.attach_alternative(body, "text/html") except TemplateDoesNotExist: logging.info("Email sent without HTML, since %s not found" % html_path) msg.send(fail_silently=fail_silently) # reset environment to original language if isinstance(recipient, User): activate(current_language)
def render_html(self, **kwargs) -> str: if self.is_mako: html = self.html_template.render(**kwargs) else: html = self.html_template.render(Context(kwargs)) if not self.pre_inline_css: html = pynliner.fromString(html) return html
def _send(recipient_pks, recipient_emails, template_path, context, from_email, fail_silently): recipients = list(User.objects.filter(pk__in=recipient_pks)) recipients += recipient_emails current_language = get_language() current_site = Site.objects.get(id=settings.SITE_ID) default_context = context or {} default_context["current_site"] = current_site default_context["STATIC_URL"] = settings.STATIC_URL subject_path = "%s/short.txt" % template_path text_path = "%s/email.txt" % template_path html_path = "%s/email.html" % template_path for recipient in recipients: # if it is user, get the email and switch the language if isinstance(recipient, User): email = recipient.email try: language = get_users_language(recipient) except LanguageStoreNotAvailable: language = None if language is not None: # activate the user's language activate(language) else: email = recipient # populate per-recipient context context = Context(default_context) context['recipient'] = recipient context['email'] = email # load email text and subject subject = render_to_string(subject_path, context) subject = "".join(subject.splitlines()) # this must be a single line text = render_to_string(text_path, context) msg = EmailMultiAlternatives(subject, text, from_email, [email]) # try to attach the html variant try: body = render_to_string(html_path, context) if getattr(settings, "TEMPLATEDEMAILS_USE_PYNLINER", False): import pynliner body = pynliner.fromString(body) msg.attach_alternative(body, "text/html") except TemplateDoesNotExist: logging.info("Email sent without HTML, since %s not found" % html_path) msg.send(fail_silently=fail_silently) # reset environment to original language if isinstance(recipient, User): activate(current_language)
def __init__(self, subject, filename): filepath = os.path.join(BASE_DIR, 'rssant/templates/email', filename) with open(filepath) as f: html = f.read() text = html2text(html) self.text_template = Template(text) html = pynliner.fromString(html) self.html_template = Template(html) self.subject = subject
def send_mail(notification_type, user, notifications): content = render_to_string('mail/%s.jinja.html' % notification_type, { 'user': user, 'notifications': notifications, }) content_with_inline_css = pynliner.fromString(content) message = EmailMessage(u'Уведомление от Mesto.UA', content_with_inline_css, settings.DEFAULT_FROM_EMAIL, [user.email]) message.content_subtype = 'html' message.send()
def send_mail(self, password=None): content = render_to_string('agency/email_add_realtor.jinja.html', { 'realtor': self, 'password': password }) content_with_inline_css = pynliner.fromString(content) message = EmailMessage(_(u'Уведомление от Mesto.UA'), content_with_inline_css, settings.DEFAULT_FROM_EMAIL, [self.user.email]) message.content_subtype = 'html' message.send()
def send(self, extra_context=None, from_email=None, headers=None): if extra_context is None: extra_context = {} if from_email is None: from_email = settings.DEFAULT_FROM_EMAIL user = self.recipient notice_type = self.notice_type formats = ( "short.txt", "full.txt", "full.html", ) context = NotificationContext({ "recipient": user, "sender": self.sender, }) context.update(extra_context) # get prerendered format messages messages = get_formatted_messages(formats, notice_type.label, context) # Strip newlines from subject subject = "".join(render_to_string("notification/email_subject.txt", { "message": messages["short.txt"], }, context).splitlines()) subject = u'%s%s' % (settings.EMAIL_SUBJECT_PREFIX, subject) body = render_to_string("notification/email_body.txt", { "message": messages["full.txt"], }, context) if self.can_send(medium="1"): recipients = [user.email] if messages['full.html']: from django.core.mail import EmailMultiAlternatives # check if premailer is enabled if settings.NOTIFICATION_USE_PYNLINER: import pynliner messages['full.html'] = pynliner.fromString(messages['full.html']) msg = EmailMultiAlternatives(subject, body, from_email, recipients, headers=headers) msg.attach_alternative(messages['full.html'], "text/html") msg.send() else: from django.core.mail.message import EmailMessage msg = EmailMessage(subject, body, from_email, recipients, headers=headers) msg.send()
def handle(self, *args, **options): now = datetime.datetime.now() print 'start', now # интервал запуска команды (должен совпадать с кроном), если потребуется чаще, можно будет сделать опцию --interval interval = datetime.timedelta(days=1) for expiration_days_delta in (-7, -3, -1, 0, +3, +7, +15): userplan_end_range = [ now - datetime.timedelta(days=expiration_days_delta) - interval, now - datetime.timedelta(days=expiration_days_delta), ] users_to_mail = User.objects.filter( is_active=True, email__gt='', subscribe_info=True, user_plans__end__range=userplan_end_range, ).exclude( user_plans__end__gt=userplan_end_range[1], # для продленных тарифов ).exclude( id__in=ActivityPeriod.objects.filter(end=None).values('user') ) utm = make_utm_dict(utm_campaign='Prodolzhenie_paketa', utm_term='Uslugi') for user in users_to_mail: print 'mail: user #%d, expiration_days_delta=%d' % (user.id, expiration_days_delta) translation.activate(user.language) subject = _(u'Напоминание об окончании тарифного плана') if expiration_days_delta < 0: content = render_to_string('paid_services/mail/plan_expired_before.jinja.html', {'days_before': -expiration_days_delta}) elif expiration_days_delta == 0: content = render_to_string( 'paid_services/mail/plan_expired.jinja.html', { 'utm': utm, 'ga_pixel': make_ga_pixel_dict(user, utm) } ) elif expiration_days_delta > 0: content = render_to_string('paid_services/mail/plan_expired_after.jinja.html', {'days_after': expiration_days_delta}) subject = _(u'Ваш аккаунт неактивен') content_with_inline_css = pynliner.fromString(content) message = EmailMessage(subject, content_with_inline_css, settings.DEFAULT_FROM_EMAIL, [user.email]) message.content_subtype = 'html' message.send()
def run(self): recipient = self.recipient if isinstance(recipient, get_user_model()): email = recipient.email try: language = get_users_language(recipient) except LanguageStoreNotAvailable: language = None if language is not None: activate(language) else: email = recipient # populate per-recipient context context = self.default_context context['recipient'] = recipient context['email'] = email # load email subject, strip and remove line breaks subject = render_to_string(self.subject_path, context).strip() subject = "".join(subject.splitlines()) # this must be a single line text = render_to_string(self.text_path, context) msg = EmailMultiAlternatives(subject, text, self.from_email, [email], headers=self.extra_headers) # try to attach the html variant try: body = render_to_string(self.html_path, context) for parser_name in pipeline: mod, member = parser_name.rsplit('.', 1) __import__(mod) module = sys.modules[mod] parser_fn = getattr(module, member) body = parser_fn(body) if pynliner: body = pynliner.fromString(body) msg.attach_alternative(body, "text/html") except TemplateDoesNotExist: logging.info("Email sent without HTML, since %s not found" % self.html_path) msg.send(fail_silently=self.fail_silently) # reset environment to original language if isinstance(recipient, get_user_model()): activate(self.current_language)
def export_templates(css_path): clean() css = u'<style type="text/css">\n%s\n</style>' % open(css_path).read() copy_tree(SOURCE_DIR, TARGET_DIR) for dirpath, dirnames, filenames in os.walk(TARGET_DIR): for fpath in (dirpath + f for f in filenames if f.endswith('.html')): contents = open(fpath).read() contents = re.sub(ur'''<style.+?</style>''', css, contents, 1) contents = pynliner.fromString(contents) with open(fpath, 'w') as f: f.write(contents.encode('utf-8'))
def send_email_to_users(recipients, template, context=None, subject_template=None, text_template=None, attachments=None): if len(recipients) == 0: return attachments = attachments or [] context = email_context(context) from_address = getattr(settings, "EMAIL_NOTIFICATION_SENDER", '"QATrack+" <*****@*****.**>') fail_silently = getattr(settings, "EMAIL_FAIL_SILENTLY", True) if subject_template: subject = render_to_string(subject_template, context).strip() else: subject = getattr(settings, "EMAIL_NOTIFICATION_SUBJECT", "QATrack+ Notification") html_content = render_to_string(template, context) html_body = pynliner.fromString(html_content) if text_template: text_body = render_to_string(text_template, context) else: text_body = strip_tags(html_body) message = EmailMultiAlternatives( subject, text_body, from_address, recipients, ) message.attach_alternative(html_body, "text/html") for name, attachment, mimetype in attachments: message.attach(name, attachment, mimetype) try: message.send(fail_silently=False) except Exception as e: # noqa: E722 # pragma: nocover logger.exception("Error sending email.") if not fail_silently: raise
def send_message(self): from profile.models import Message from_user = self.agency.realtors.filter(is_admin=True).first().user content = render_to_string('agency/message_add_realtor.jinja.html', {'realtor': self}) content_with_inline_css = pynliner.fromString(content) new_message = Message(to_user=self.user, from_user=from_user, title=_(u'Уведомление от Mesto.UA'), text=content_with_inline_css, text_type='html') new_message.save() new_message.hidden_for_user.add(from_user)
def sendmail_with_template(template, to, subject, cc=None, bcc=None, headers=None, **kwargs): """ Sends an email with the selected html template. html templates can be found inside the broadgauge/templates directory. Params: ======= template: str Link to the html file to be used as template. The html file is parsed by Jinja Templating before sending to the recipient. Keyword Args: ============= to: str Recipient's email sub: str Subject of the mail P.S: Other keywords are sent to Jinja Templating Language for direct parsing, as it is. Example: >>> from sendmail import sendmail >>> sendmail("emails/trainers/welcome.html",to=..."some_email.com", sub="Hey Friend!", variable1=var, variable2=var2) Email sent to some_email.com """ html = render_template(template, **kwargs) # inline CSS to make mail clients happy html = pynliner.fromString(html) return sendmail(to_address=to, subject=subject, message_html=html, headers=headers, cc=cc, bcc=bcc, **kwargs)
def send_email(html, subject, recipients): html = pynliner.fromString( html ) # pynliner turns css stylesheets into inline styles, because gmail + other clients disallow style sheets plain_text = html2text.html2text( html ) # because we _must_ provide a plain-text alternative message body for recip in recipients: if recip.split("_")[0] == "hacker": #print "Not sending email to " + str(recip) return mail.send_mail(sender="Hack@Brown 2015 <*****@*****.**>", to=recip, subject=subject, body=plain_text, html=html) print "SENDING EMAIL to " + str(recip)
def create_developer(self): if self.is_developer(): raise Exception( 'Cannot create developer: user #%d is developer already' % self.id) elif self.get_agency(): raise Exception('Cannot create developer: user #%d has an agency' % self.id) else: from newhome.models import Developer Developer.objects.create(user=self, name=unicode(self), is_cabinet_enabled=True) # код от А.Миленко (ранее вызывался при *регистрации* юзера-застройщика), немного упрощенный: # При создании нового застройщика, отправляю письмо ответственному лицу # Данный функционал НЕ вынесен в сигнал, т.к. нужно чтобы при возможности был телефон нового застройщика # todo: вынести в Notification и сигналы from django.core.mail import EmailMessage, send_mail from django.contrib.auth.models import Permission from django.template.loader import render_to_string import pynliner perm = Permission.objects.get(codename='newhome_notification') emails = User.objects.filter( Q(groups__permissions=perm) | Q(user_permissions=perm)).values_list('email', flat=True) for email in emails: send_mail(u'Mesto.UA: Регистрация застройщика', u'Зарегестрирован новый застройщик %s' % self.email, settings.DEFAULT_FROM_EMAIL, [email]) # Отпраялвяем письмо-инструкцию застройщику translation.activate(self.language) subject = _(u'Письмо-инструкция по работе с сайтом mesto.ua') content = render_to_string( 'mail/newhome/new_developer_%s.jinja.html' % self.language, {'user': self}) content_with_inline_css = pynliner.fromString(content) message = EmailMessage(subject, content_with_inline_css, settings.DEFAULT_FROM_EMAIL, [self.email]) message.content_subtype = 'html' message.send()
def with_inline_css(html_without_css): """Returns html with inline css if the css file path exists else returns html with out the inline css. """ css_filepath = settings.NOTIFICATION_EMAIL_CSS if not css_filepath.startswith('/'): css_filepath = file_path_finder(settings.NOTIFICATION_EMAIL_CSS) if css_filepath: with open(css_filepath, "r") as _file: css_content = _file.read() # insert style tag in the html and run pyliner. html_with_inline_css = pynliner.fromString('<style>' + css_content + '</style>' + html_without_css) return html_with_inline_css return html_without_css
def sendmail(to_address, subject, message, message_html=None, reply_to=None, cc=None, bcc=None): if 'SMTP_SERVER' not in app.config: app.logger.warn("SMTP_SERVER config is not set, ignoring sendmail...") return app.logger.info("sending mail to %s with subject %r", to_address, subject) headers = {} if reply_to: headers['Reply-To'] = reply_to if message_html: message_html = pynliner.fromString(message_html) if Unsubscribe.contains(to_address): app.logger.warn("%s is in the unsubscribed list. Not sending email.", to_address) return envelope = Envelope(from_addr=app.config['FROM_ADDRESS'], to_addr=to_address, subject=subject, text_body=message, html_body=message_html, headers=headers, cc_addr=cc, bcc_addr=bcc) server = app.config['SMTP_SERVER'] port = app.config.get('SMTP_PORT', 25) username = app.config['SMTP_USERNAME'] password = app.config['SMTP_PASSWORD'] tls = app.config.get('SMTP_STARTTLS', False) envelope.send(host=server, port=port, login=username, password=password, tls=tls) app.logger.info("mail sent to %s with subject %r", to_address, subject)
def sendmail_with_template( template, to, subject, cc=None, bcc=None, headers=None, **kwargs ): """ Sends an email with the selected html template. html templates can be found inside the broadgauge/templates directory. Params: ======= template: str Link to the html file to be used as template. The html file is parsed by Jinja Templating before sending to the recipient. Keyword Args: ============= to: str Recipient's email sub: str Subject of the mail P.S: Other keywords are sent to Jinja Templating Language for direct parsing, as it is. Example: >>> from sendmail import sendmail >>> sendmail("emails/trainers/welcome.html",to=..."some_email.com", sub="Hey Friend!", variable1=var, variable2=var2) Email sent to some_email.com """ html = render_template(template, **kwargs) # inline CSS to make mail clients happy html = pynliner.fromString(html) return sendmail(to_address=to, subject=subject, message_html=html, headers=headers, cc=cc, bcc=bcc, **kwargs)
def send_mail(record): template_filename = 'psi_mail_hosts_load.mako' template_lookup = TemplateLookup(directories=[os.path.dirname(os.path.abspath('__file__'))]) # SECURITY IMPORTANT: `'h'` in the `default_filters` list causes HTML # escaping to be applied to all expression tags (${...}) in this # template. Because we're output untrusted user-supplied data, this is # essential. template = Template(filename=template_filename, default_filters=['unicode', 'h'], lookup=template_lookup) try: rendered = template.render(data=record) except: raise Exception(exceptions.text_error_template().render()) # CSS in email HTML must be inline rendered = pynliner.fromString(rendered) log_diagnostics('Sending email...') sender.send(config['statsEmailRecipients'], config['emailUsername'], 'Psiphon 3 Host Load Stats', repr(record), rendered) log_diagnostics('Email sent.')
def send_mail(record, subject='PSI Ansible Report', template_filename=MAKO_TEMPLATE): if not os.path.isfile(template_filename): raise template_lookup = TemplateLookup(directories=[os.path.dirname(os.path.abspath('__file__'))]) template = Template(filename=template_filename, default_filters=['unicode', 'h'], lookup=template_lookup) try: rendered = template.render(data=record) except: raise Exception(exceptions.text_error_template().render()) # CSS in email HTML must be inline rendered = pynliner.fromString(rendered) sender.send(config['emailRecipients'], config['emailUsername'], subject, None, rendered)
def with_inline_css(html_without_css): """ returns html with inline css if css file path exists else returns html with out the inline css. """ css_filepath = const.NOTIFICATION_DIGEST_EMAIL_CSS if not css_filepath.startswith('/'): css_filepath = finders.AppDirectoriesFinder().find(const.NOTIFICATION_DIGEST_EMAIL_CSS) if css_filepath: with open(css_filepath, "r") as _file: css_content = _file.read() # insert style tag in the html and run pyliner. html_with_inline_css = pynliner.fromString('<style>' + css_content + '</style>' + html_without_css) return html_with_inline_css return html_without_css
def _render_email(data): logger.debug_log('_render_email: enter') global _template if not _template: _template = Template(filename='templates/feedback_response.mako', default_filters=['unicode', 'h', 'decode.utf8'], input_encoding='utf-8', output_encoding='utf-8', lookup=TemplateLookup(directories=['.'])) logger.debug_log('_render_email: template loaded') rendered = _template.render(data=data) # CSS in email HTML must be inline rendered = pynliner.fromString(rendered) logger.debug_log('_render_email: exiting with len(rendered)=%d' % len(rendered)) return rendered
def sendmail(to_address, subject, message, message_html=None, reply_to=None, cc=None, bcc=None): if 'SMTP_SERVER' not in app.config: app.logger.warn("SMTP_SERVER config is not set, ignoring sendmail...") return app.logger.info("sending mail to %s with subject %r", to_address, subject) headers = {} if reply_to: headers['Reply-To'] = reply_to if message_html: message_html = pynliner.fromString(message_html) if Unsubscribe.contains(to_address): app.logger.warn("%s is in the unsubscribed list. Not sending email.", to_address) return envelope = Envelope( from_addr=app.config['FROM_ADDRESS'], to_addr=to_address, subject=subject, text_body=message, html_body=message_html, headers=headers, cc_addr=cc, bcc_addr=bcc ) server = app.config['SMTP_SERVER'] port = app.config.get('SMTP_PORT', 25) username = app.config['SMTP_USERNAME'] password = app.config['SMTP_PASSWORD'] tls = app.config.get('SMTP_STARTTLS', False) envelope.send( host=server, port=port, login=username, password=password, tls=tls) app.logger.info("mail sent to %s with subject %r", to_address, subject)
def run(self): recipient = self.recipient if isinstance(recipient, get_user_model()): email = recipient.email try: language = get_users_language(recipient) except LanguageStoreNotAvailable: language = None if language is not None: activate(language) else: email = recipient # populate per-recipient context context = Context(self.default_context) context['recipient'] = recipient context['email'] = email # load email subject, strip and remove line breaks subject = render_to_string(self.subject_path, context).strip() subject = "".join(subject.splitlines()) # this must be a single line text = render_to_string(self.text_path, context) msg = EmailMultiAlternatives( subject, text, self.from_email, [email], headers=self.extra_headers) # try to attach the html variant try: body = render_to_string(self.html_path, context) if pynliner: body = pynliner.fromString(body) msg.attach_alternative(body, "text/html") except TemplateDoesNotExist: logging.info("Email sent without HTML, since %s not found" % self.html_path) msg.send(fail_silently=self.fail_silently) # reset environment to original language if isinstance(recipient, get_user_model()): activate(self.current_language)
def convert_one(part, config): try: text = part.get_payload(None, True) if not text.startswith('!m'): return None text = re.sub('\s*!m\s*', '', text, re.M) if '\n-- \n' in text: pre_signature, signature = text.split('\n-- \n') md = markdown.markdown(pre_signature, output_format="html5") md += '\n<div class="signature" style="font-size: small"><p>-- <br />' md += '<br />'.join(signature.split('\n')) md += '</p></div>' else: md = markdown.markdown(text) if config.css: md = '<style>' + config.css + '</style>' + md md = pynliner.fromString(md) message = MIMEText(md, 'html') return message except Exception: return None
def with_inline_css(html_without_css): """Returns html with inline css if the css file path exists else returns html with out the inline css. """ css_filepath = settings.NOTIFICATION_EMAIL_CSS if not css_filepath.startswith('/'): css_filepath = file_path_finder(settings.NOTIFICATION_EMAIL_CSS) if css_filepath: with open(css_filepath, "r") as _file: css_content = _file.read() # pynliner imports cssutils, which has an expensive initialization. All # told, it can account for 15-20% of "fast" LMS startup (without asset # compilation). So we're going to load it locally here so that we delay # that one-time hit until we actually do the (rare) operation that is # sending a credit notification email. import pynliner # insert style tag in the html and run pyliner. html_with_inline_css = pynliner.fromString('<style>' + css_content + '</style>' + html_without_css) return html_with_inline_css return html_without_css
def process_text(self, input_text): return pynliner.fromString(input_text)
def test_07_fromString(self): """Test 'fromString' complete""" output = pynliner.fromString(self.html) desired = u'<h1 style="color: #fc0">Hello World!</h1>' self.assertEqual(output, desired)
def test_07_fromString(self): """Test 'fromString' complete""" output = pynliner.fromString(self.html) desired = u'<span class="b1" style="font-weight: bold">Bold</span><span class="b2 c" style="font-weight: bold; color: red">Bold Red</span>' self.assertEqual(output, desired)
def send_now(users, label, extra_context=None, on_site=True, sender=None, attachments=[],\ obj_instance=None, force_send=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 extra_context is None: extra_context = {} 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', 'full.txt', 'notice.html', 'full.html', 'sms.txt', ) # TODO make formats configurable 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) # update context with user specific translations context = Context({ "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('notification/email_subject.txt', { 'message': messages['short.txt'], }, context).splitlines()) body = render_to_string('notification/email_body.txt', { 'message': messages['full.txt'], }, context) body = pynliner.fromString(body) on_site = should_send(user, notice_type, "2", obj_instance) #On-site display notice = Notice.objects.create(recipient=user, message=messages['notice.html'], notice_type=notice_type, on_site=on_site, sender=sender) if (should_send(user, notice_type, "1", obj_instance) or force_send) and user.email and user.is_active: # Email recipients.append(user.email) # send empty "plain text" data msg = EmailMultiAlternatives(subject, "", settings.DEFAULT_FROM_EMAIL, recipients) # attach html data as alternative msg.attach_alternative(body, "text/html") for attachment in attachments: msg.attach(attachment) try: msg.send() email_sent.send(sender=Notice, user=user, notice_type=notice_type, obj=obj_instance) notifications_logger.info("SUCCESS:EMAIL:%s: data=(notice_type=%s, subject=%s)"%(user, notice_type, subject)) except: notifications_logger.exception("ERROR:EMAIL:%s: data=(notice_type=%s, subject=%s)"%(user, notice_type, subject)) if should_send(user, notice_type, "3", obj_instance) and user.userprofile.sms and user.is_active: try: rc = TwilioRestClient(TWILIO_ACCOUNT_SID, TWILIO_ACCOUNT_TOKEN) rc.sms.messages.create(to=user.userprofile.sms, from_=TWILIO_CALLER_ID, body=messages['sms.txt']) sms_sent.send(sender=Notice, user=user, notice_type=notice_type, obj=obj_instance) notifications_logger.info("SUCCESS:SMS:%s: data=(notice_type=%s, msg=%s)"%(user, notice_type, messages['sms.txt'])) except: notifications_logger.exception("ERROR:SMS:%s: data=(notice_type=%s, msg=%s)"%(user, notice_type, messages['sms.txt'])) # reset environment to original language activate(current_language)
def _send(recipient_pks, recipient_emails, template_path, context, from_email, fail_silently, extra_headers=None): recipients = list(get_user_model().objects.filter(pk__in=recipient_pks)) recipients += recipient_emails current_language = get_language() current_site = Site.objects.get(id=settings.SITE_ID) default_context = context or {} default_context["current_site"] = current_site default_context["STATIC_URL"] = settings.STATIC_URL subject_path = "%s/short.txt" % template_path text_path = "%s/email.txt" % template_path html_path = "%s/email.html" % template_path for recipient in recipients: if use_threading: SendThread(recipient, current_language, current_site, default_context, subject_path, text_path, html_path, from_email, fail_silently).start() return # if it is user, get the email and switch the language if isinstance(recipient, get_user_model()): email = recipient.email try: language = get_users_language(recipient) except LanguageStoreNotAvailable: language = None if language is not None: # activate the user's language activate(language) else: email = recipient # populate per-recipient context context = Context(default_context) context['recipient'] = recipient context['email'] = email # load email subject, strip and remove line breaks subject = render_to_string(subject_path, context).strip() subject = "".join(subject.splitlines()) # this must be a single line text = render_to_string(text_path, context) msg = EmailMultiAlternatives(subject, text, from_email, [email], headers=extra_headers) # try to attach the html variant try: body = render_to_string(html_path, context) if pynliner: body = pynliner.fromString(body) msg.attach_alternative(body, "text/html") except TemplateDoesNotExist: logging.info("Email sent without HTML, since %s not found" % html_path) msg.send(fail_silently=fail_silently) # reset environment to original language if isinstance(recipient, get_user_model()): activate(current_language) return msg
def send_now(users, label, extra_context=None, on_site=True, sender=None, from_email=settings.DEFAULT_FROM_EMAIL, headers=None): """ 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 extra_context is None: extra_context = {} 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', 'full.txt', 'notice.html', 'full.html', ) # TODO make formats configurable 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) # update context with user specific translations context = Context({ "recipient": user, "sender": sender, "notice": ugettext(notice_type.display), "notices_url": notices_url, "current_site": current_site, "STATIC_URL": settings.STATIC_URL, }) context.update(extra_context) # get prerendered format messages messages = get_formatted_messages(formats, label, context) # Strip newlines from subject subject = ''.join(render_to_string('notification/email_subject.txt', { 'message': messages['short.txt'], }, context).splitlines()) body = render_to_string('notification/email_body.txt', { 'message': messages['full.txt'], }, context) Notice.objects.create(recipient=user, message=messages['notice.html'], notice_type=notice_type, on_site=on_site, sender=sender) if should_send(user, notice_type, "1") and user.email and user.is_active: recipients.append(user.email) if messages['full.html']: from django.core.mail import EmailMultiAlternatives # check if premailer is enabled if getattr(settings, "NOTIFICATION_USE_PYNLINER", False): import pynliner messages['full.html'] = pynliner.fromString(messages['full.html']) msg = EmailMultiAlternatives(subject, body, from_email, recipients, headers=headers) msg.attach_alternative(messages['full.html'], "text/html") msg.send() else: msg = EmailMessage(subject, body, from_email, recipients, headers=headers) msg.send() # reset environment to original language activate(current_language)
def test_double_comment(self): self.html = """<!-- comment -->""" output = pynliner.fromString(self.html) self.assertTrue("<!--<!--" not in output)
def test_double_doctype(self): self.html = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">""" output = pynliner.fromString(self.html) self.assertNotIn("<!<!", output)
def test_double_comment(self): self.html = """<!-- comment -->""" output = pynliner.fromString(self.html) self.assertNotIn("<!--<!--", output)