Example #1
0
def send_single_email(user, email, subject, title, message):
    message = escape(message)
    message = message.replace("~br~", "<br>")
    email_vars = {"preheader": "", "title": title, "message": message}
    email_string = render_to_string('email_without_button.html',
                                    {'email': email_vars})

    if "SENDGRID_API_KEY" in os.environ:
        sg = sendgrid.SendGridAPIClient(
            apikey=os.environ.get('SENDGRID_API_KEY'))
        from_email = sendgrid.Email(settings.FROM_EMAIL)
        to_email = sendgrid.Email(email)
        subject = subject
        content = Content("text/html", email_string)
        mail = Mail(from_email, subject, to_email, content)
        response = sg.client.mail.send.post(request_body=mail.get())

        if response.status_code == 202:
            log_user_event(user, "Sent email with subject: " + subject,
                           "email", "Email content: " + message)
            return True
        else:
            return False

    log_user_event(user, "Failed to send email with subject: " + subject,
                   "email", "Email content: " + message)
    raise RuntimeError("No SendGrid API key found in environment variables.")
Example #2
0
    def send_email(self, email: mail_.Email) -> bool:
        mail = sg_mail.Mail()
        personalization = sg_mail.Personalization()
        mail.set_from(sendgrid.Email(email.sender[1], email.sender[0]))
        mail.set_subject(email.subject)
        mail.add_content(sg_mail.Content("text/plain", email.content))

        for recipient in email.recipients:
            personalization.add_to(sendgrid.Email(recipient))

        if email.cc:
            for recipient in email.cc:
                personalization.add_cc(sendgrid.Email(recipient))

        if email.bcc:
            for recipient in email.bcc:
                personalization.add_bcc(sendgrid.Email(recipient))

        mail.add_personalization(personalization)
        response = self._sg_client.client.mail.send.post(
            request_body=mail.get())

        if response.status_code in [202, 250]:
            return True
        elif response.status_code == 421:
            raise exceptions_.ServiceRateLimitException(self.name)
        elif response.status_code in [450, 550, 551, 552, 553]:
            exceptions_.InvalidRecipientException(self.name)
        else:
            exceptions_.GenericEmailServiceException(self.name)

        return False
Example #3
0
def sendgrid_email(recipient, subject, msg):
    sg = sendgrid.SendGridAPIClient(apikey=SENDGRID_API_KEY)
    from_email = sendgrid.Email("*****@*****.**")
    to_email = sendgrid.Email(recipient)
    html_msg = "<p>%s</p>" % msg
    content = Content("text/html", html_msg)
    mail_to_send = Mail(from_email, subject, to_email, content)
    response = sg.client.mail.send.post(request_body=mail_to_send.get())
    print "email nudge sent to user", response.status_code
Example #4
0
def send_email(subject, to, template_name, context):
    sendgrid_client = sendgrid.SendGridAPIClient(apikey=settings.SENDGRID_API_KEY)

    from_email = sendgrid.Email(settings.DEFAULT_FROM_EMAIL)
    to_email = sendgrid.Email(to)
    content = Content("text/plain", render_to_string(template_name, context))

    mail = Mail(from_email, subject, to_email, content)
    return sendgrid_client.client.mail.send.post(request_body=mail.get())
Example #5
0
def send_email(email):
    sg = sendgrid.SendGridAPIClient(apikey=SENDGRIDAPI)
    from_email = sendgrid.Email("*****@*****.**")
    to_email = sendgrid.Email(email)
    subject = "Sending with SendGrid is Fun"
    content = sendgrid.Content("text/plain",
                               "and easy to do anywhere, even with Python")
    mail = sendgrid.Mail(from_email, subject, to_email, content)
    response = sg.client.mail.send.post(request_body=mail.get())
    print(response.status_code)
    print(response.body)
    print(response.headers)
Example #6
0
def sendgrid_send_data_missing_email(msg, recipient):
    sg = sendgrid.SendGridAPIClient(apikey=SENDGRID_API_KEY)
    from_email = sendgrid.Email("*****@*****.**")
    to_email = sendgrid.Email(recipient)
    subject = "Beehive: Rescuetime data missing notification"
    logo_path = './static/images/beehive.png'
    content = Content("text/html", "<p>Hi,</p>" + "<p>Beehive has detected some rescuetime data issues. " \
                      + msg + " Please login to the rescuetime dashboard to see details. </p>" \
                                    " <p> Dashboard: https://slm.smalldata.io/rescuetime/stats?days=7" + "</p>" \
                                    "<br> <p> The Beehive team </p>")

    mail_to_send = Mail(from_email, subject, to_email, content)
    response = sg.client.mail.send.post(request_body=mail_to_send.get())
    print "store_rescuetime_data: sendgrid email response code,",response.status_code
Example #7
0
    def send(self):
        sg = sendgrid.SendGridAPIClient(api_key=self.context.sendgrid_api_key)
        markdowner = Markdown(extras=["tables"])

        from_email = sendgrid.Email(self.context.from_email)
        body = []
        for a in self.analyses:
            stale_days = (datetime.datetime.now(tz=a.last_change.tzinfo) - a.last_change).days if a.last_change else "Never updated"
            body.append(line_item_template.format(file_path=a.doc_name, file_link=a.file_link,
                                                  changed_by=a.changed_by_email, stale_days=stale_days))

        plain_text = body_template.format(item_list="\n".join(body),
                                          github_repo=self.context.github_repo,
                                          github_repo_root=self.context.github_repo_path,
                                          max_stale_days=self.context.doc_is_stale_after_days)
        html_text = markdowner.convert(plain_text)

        content_text = sendgrid.Content("text/plain", plain_text)
        content_html = sendgrid.Content("text/html", html_text + "\n" + css)

        recipients = list(map(lambda x: sendgrid.To(x), self.recipients))
        mail = sendgrid.Mail(from_email, recipients, self.subject(), plain_text_content=content_text,
                             html_content=content_html)
        response = sg.client.mail.send.post(request_body=mail.get())

        if 300 > response.status_code >= 200:
            success(f"Successfully sent email to {', '.join(self.recipients)} regarding {len(self.analyses)} files", 2)
        else:
            error(
                f"Failed to send email to {', '.join(self.recipients)} regarding {len(self.analyses)} files: "
                f"{response.status_code} - {response.body}", 2)
Example #8
0
def send_templated_notification_simple(email, template_id, group_id, category):
    """
    Send an email based on a template.
    :param str email: The email recipient
    :param str template_id: The template ID of the email.
    :param str template_id: The group ID of the email.
    pass to the email template.
    """
    mail = sendgrid.helpers.mail.Mail()

    mail.from_email = sendgrid.Email("*****@*****.**", "Halite Challenge")
    personalization = sendgrid.helpers.mail.Personalization()
    personalization.add_to(sendgrid.helpers.mail.Email(email, email))

    mail.add_personalization(personalization)
    mail.template_id = template_id
    mail.asm = sendgrid.helpers.mail.ASM(group_id, [
        config.GOODNEWS_ACCOMPLISHMENTS, config.GAME_ERROR_MESSAGES,
        config.RESEARCH_EMAILS, config.NEWSLETTERS_ARTICLES
    ])
    mail.add_category(sendgrid.helpers.mail.Category(category))
    settings = sendgrid.helpers.mail.MailSettings()
    settings.sandbox_mode = sendgrid.helpers.mail.SandBoxMode(
        config.SENDGRID_SANDBOX_MODE)
    mail.mail_settings = settings

    response = sg.client.mail.send.post(request_body=mail.get())
    print(response.status_code)
Example #9
0
    def email_profile_to(self, to_email):
        causes = self.causes.all()
        causes_string = "none :("

        if causes.count() == 3:
            causes_string = "{}, {} and {}".format(causes[0], causes[1],
                                                   causes[2])
        elif causes.count() == 2:
            causes_string = "{} and {}".format(causes[0], causes[1])
        elif causes.count() == 1:
            causes_string = causes[0]

        message = "{} has just signed up. Their membership level is {} and their selected causes are {}. " \
                  "Their email is {}.".format(self.get_full_name(), self.member_type, causes_string, self.user.email)
        email_vars = {
            "preheader": "",
            "title": "New member signup",
            "message": message
        }
        email_string = render_to_string('email_without_button.html',
                                        {'email': email_vars})
        subject = "A new member signed up! ({})".format(self.get_full_name())

        if "SENDGRID_API_KEY" in os.environ:
            sg = sendgrid.SendGridAPIClient(
                apikey=os.environ.get('SENDGRID_API_KEY'))

            from_email = sendgrid.Email(settings.FROM_EMAIL)
            to_email = sendgrid.Email(to_email)
            content = Content("text/html", email_string)
            mail = Mail(from_email, subject, to_email, content)
            response = sg.client.mail.send.post(request_body=mail.get())

            if response.status_code == 202:
                log_user_event(self.user,
                               "Sent email with subject: " + subject, "email",
                               "Email content: " + email_string)
                return True

        log_user_event(self.user,
                       "Failed to send email with subject: " + subject,
                       "email", "Email content: " + email_string)
        return False
Example #10
0
    def __send_email(self, subject, body):
        if "SENDGRID_API_KEY" in os.environ:
            sg = sendgrid.SendGridAPIClient(
                apikey=os.environ.get('SENDGRID_API_KEY'))
            from_email = sendgrid.Email(settings.FROM_EMAIL)
            to_email = sendgrid.Email(self.email)
            subject = subject
            content = Content("text/html", body)
            mail = Mail(from_email, subject, to_email, content)
            response = sg.client.mail.send.post(request_body=mail.get())

            if response.status_code == 202:
                log_user_event(self, "Sent email with subject: " + subject,
                               "email", "Email content: " + body)
                return True

        log_user_event(self, "Failed to send email with subject: " + subject,
                       "email", "Email content: " + body)
        raise RuntimeError(
            "No SendGrid API key found in environment variables.")
Example #11
0
async def mailviasendgrid(message_str):
    mylog(u"mailing via sendgrid")
    sg_username = config.SENDGRID_USERNAME
    sg_recipient = config.SENDGRID_RECIPIENT
    sg_apikey = config.SENDGRID_APIKEY
    sg_client = sendgrid.SendGridAPIClient(sg_apikey)
    sg_from = sendgrid.Email(email=sg_username, name="IP Address Checker")
    message = sendgrid.Mail(from_email=sg_from,
                            to_emails=[sg_recipient],
                            subject=u"Update of IP Address",
                            plain_text_content=message_str)
    message.reply_to = sg_recipient
    sg_client.send(message)
    def send_email(receivers,
                   subject,
                   content,
                   template_id=None,
                   text_replacements=None,
                   sender_name=None,
                   sender_email=None,
                   attachments=None,
                   cc_list=None,
                   bcc_list=None):
        print(os.environ.get('SENDGRID_API_KEY'), '   is the sendgrid api key')
        sendgrid_client = sendgrid.SendGridAPIClient(
            api_key=os.environ.get('SENDGRID_API_KEY'))
        sender = sendgrid.Email(name=sender_name, email=sender_email)
        mail = Mail(from_email=sender, subject=subject, content=content)

        personalization = Personalization()

        if len(receivers) == 0:
            error = Error({'detail': 'Please enter receiver mailId'},
                          status=status.HTTP_400_BAD_REQUEST)
            return error, None
        else:
            for receiver in receivers:
                personalization.add_to(receiver)
        personalization.add_to(receivers[0])

        for cc in cc_list and cc_list is not None:
            personalization.add_cc(cc)

        for bcc in bcc_list and bcc_list is not None:
            personalization.add_bcc(bcc)

        mail.add_personalization(personalization)

        if text_replacements is not None:
            for text_replacement in text_replacements:
                for key, value in text_replacement.items():
                    mail.personalizations[0].add_substitution(
                        Substitution(key, value))
        mail.template_id = template_id

        if attachments is not None:
            for attachment in attachments:
                mail.add_attachment(attachment)

        response = sendgrid_client.client.mail.send.post(
            request_body=mail.get())
        return {'status': True, 'response': response.body.decode().strip()}
Example #13
0
def send_mail(message_str, subject, attach_html=None):
    sys.stderr.write("[info] mailing via sendgrid\n")
    sg_from = os.environ["SENDGRID_FROM"]
    sg_recipient = os.environ["SENDGRID_RECIPIENT"]
    sg_apikey = os.environ["SENDGRID_API_KEY"]
    sg_client = sendgrid.SendGridAPIClient(sg_apikey)

    sg_from = sendgrid.Email(name="Check Kindle Price", email=sg_from)
    message = sendgrid.Mail(from_email=sg_from,
                            to_emails=[sg_recipient],
                            subject=subject,
                            html_content=message_str)
    message.reply_to = sg_recipient
    if attach_html:
        attachment_file = sendgrid.Attachment(
            file_content=base64.b64encode(attach_html).decode(),
            file_type="text/html",
            file_name="attach.html")
        message.add_attachment(attachment_file)
    sg_client.send(message)
Example #14
0
def send_templated_notification(recipient, template_id, substitutions,
                                group_id, category):
    """
    Send an email based on a template.
    :param Recipient recipient: The recipient of the email
    :param str template_id: The template ID of the email.
    :param Dict[str, Any] substitutions: Any other substitution variables to
    :param str group_id: The group ID of the email.
    pass to the email template.
    """
    mail = sendgrid.helpers.mail.Mail()

    if not recipient.organization:
        recipient = recipient._replace(organization="(no affiliation)")

    mail.from_email = sendgrid.Email("*****@*****.**", "Halite Challenge")
    personalization = sendgrid.helpers.mail.Personalization()
    personalization.add_to(
        sendgrid.helpers.mail.Email(recipient.email, recipient.username))

    all_substitutions = itertools.chain(recipient._asdict().items(),
                                        substitutions.items())
    for substitution_key, substitution_value in all_substitutions:
        personalization.add_substitution(
            sendgrid.helpers.mail.Substitution("-{}-".format(substitution_key),
                                               substitution_value))

    mail.add_personalization(personalization)
    mail.template_id = template_id
    mail.asm = sendgrid.helpers.mail.ASM(group_id, [
        config.GOODNEWS_ACCOMPLISHMENTS, config.GAME_ERROR_MESSAGES,
        config.RESEARCH_EMAILS, config.NEWSLETTERS_ARTICLES
    ])
    mail.add_category(sendgrid.helpers.mail.Category(category))
    settings = sendgrid.helpers.mail.MailSettings()
    settings.sandbox_mode = sendgrid.helpers.mail.SandBoxMode(
        config.SENDGRID_SANDBOX_MODE)
    mail.mail_settings = settings

    response = sg.client.mail.send.post(request_body=mail.get())
    print(response.status_code)
Example #15
0
def send_notification(recipient_email, recipient_name, subject, body,
                      attachments=None):
    mail = sendgrid.helpers.mail.Mail()

    mail.from_email = sendgrid.Email("*****@*****.**", "Halite Challenge")
    personalization = sendgrid.helpers.mail.Personalization()
    personalization.add_to(sendgrid.helpers.mail.Email(recipient_email, recipient_name))
    personalization.subject = "Halite Challenge: " + subject
    mail.add_personalization(personalization)

    mail.add_content(sendgrid.helpers.mail.Content("text/html", body))

    settings = sendgrid.helpers.mail.MailSettings()
    settings.sandbox_mode = sendgrid.helpers.mail.SandBoxMode(config.SENDGRID_SANDBOX_MODE)
    mail.mail_settings = settings

    try:
        response = sg.client.mail.send.post(request_body=mail.get())
    except HTTPError as e:
        app.logger.error("Could not send email", exc_info=e)
        app.logger.error("Response: {}".format(e.body))
Example #16
0
def send_notification(recipient_email,
                      recipient_name,
                      subject,
                      body,
                      attachments=None):
    mail = sendgrid.helpers.mail.Mail()

    mail.from_email = sendgrid.Email("*****@*****.**", "Halite Challenge")
    personalization = sendgrid.helpers.mail.Personalization()
    personalization.add_to(
        sendgrid.helpers.mail.Email(recipient_email, recipient_name))
    personalization.subject = "Halite Challenge: " + subject
    mail.add_personalization(personalization)

    mail.add_content(sendgrid.helpers.mail.Content("text/html", body))

    settings = sendgrid.helpers.mail.MailSettings()
    settings.sandbox_mode = sendgrid.helpers.mail.SandBoxMode(
        config.SENDGRID_SANDBOX_MODE)
    mail.mail_settings = settings

    response = sg.client.mail.send.post(request_body=mail.get())
Example #17
0
def overdue_cron(request):
    if "XERO_CONSUMER_KEY" in os.environ:
        with open(xero_rsa) as keyfile:
            rsa_key = keyfile.read()
        credentials = PrivateCredentials(
            os.environ.get('XERO_CONSUMER_KEY', "/usr/src/data/xerkey.pem"),
            rsa_key)
        xero = Xero(credentials)

        # Monkey patch the library to support pagination.
        def get_contacts(page):
            uri = '/'.join([
                xero.contacts.base_url, xero.contacts.name,
                "?page=" + str(page)
            ])
            params = {'summarizeErrors': False}
            return uri, params, 'get', None, None, False

        xero.contacts.get_contacts = xero.contacts._get_data(get_contacts)

        contacts = list()
        page = 0

        while True:
            page += 1
            result = xero.contacts.get_contacts(page)
            contacts += result

            if not result:
                break

        profiles = Profile.objects.all()
        deactivated_members = list()
        activated_members = list()

        for contact in contacts:
            if contact.get('IsCustomer', False) and contact.get(
                    'ContactStatus', False) == "ACTIVE":
                contact_id = contact['ContactID']
                try:
                    profile = profiles.get(xero_account_id=contact_id)
                    if contact.get("Balances", False):
                        print(contact["Balances"]["AccountsReceivable"]
                              ["Outstanding"])
                        if contact["Balances"]["AccountsReceivable"][
                                "Outstanding"] > 0:
                            if profile.state == "active":
                                profile.deactivate()
                                deactivated_members.append(
                                    profile.get_full_name())
                        else:
                            if profile.state == "inactive":
                                profile.activate()
                                activated_members.append(
                                    profile.get_full_name())

                    else:
                        if profile.state == "inactive":
                            profile.activate()
                            activated_members.append(profile.get_full_name())

                except ObjectDoesNotExist:
                    pass

        if "SENDGRID_API_KEY" in os.environ and len(
                deactivated_members) or len(activated_members):
            body = "HSBNE overdue fees check ran with {} overdue. These people have been deactivated:<br>{}<br><br>" \
                   "These people have been reactivated:<br>{}".format(len(deactivated_members), deactivated_members,
                                                                      activated_members)
            sg = sendgrid.SendGridAPIClient(
                apikey=os.environ.get('SENDGRID_API_KEY'))
            from_email = sendgrid.Email(settings.FROM_EMAIL_TREASURER)
            to_email = sendgrid.Email(settings.SYSADMIN_EMAIL)
            subject = "HSBNE overdue fees check ran with {} overdue and {} reactivated.".format(
                len(deactivated_members), len(activated_members))
            content = sendgrid.helpers.mail.Content("text/html", body)
            mail = sendgrid.helpers.mail.Mail(from_email, subject, to_email,
                                              content)
            sg.client.mail.send.post(request_body=mail.get())

        return HttpResponse(str(page) + "," + str(len(contacts)))

    else:
        return "Error checking overdue fees in Xero. No Xero API details."
Example #18
0
    def send_via_sendgrid(self, transport, mail, embedded_images, config):
        api_key = None
        if 'apiKey' in transport:
            api_key = transport['apiKey']
        if os.getenv('SENDGRID_API_KEY'):
            api_key = os.getenv('SENDGRID_API_KEY')
        if not api_key:
            raise NotConfiguredException('No Sendgrid API key configured!')

        sg = sendgrid.SendGridAPIClient(api_key=api_key)
        from_email = sendgrid.Email(mail['mail_from'])
        to_email = sendgrid.To(mail['mail_to'])
        text_content = None
        if mail['text_body'] != '':
            text_content = sendgrid.Content('text/plain', mail['text_body'])
        sendgrid_mail = sendgrid.Mail(from_email, to_email,
                                      mail['mail_subject'], text_content)
        if mail['html_body'] != '':
            html_content = sendgrid.Content('text/html', mail['html_body'])
            sendgrid_mail.add_content(html_content)
        if len(embedded_images) > 0:
            for file_name, content in embedded_images.items():
                attachment = Attachment()
                attachment.file_content = base64.b64encode(content).decode()
                attachment.file_type = 'application/octet-stream'
                attachment.file_name = file_name
                attachment.disposition = 'inline'
                attachment.content_id = file_name
                sendgrid_mail.attachment = attachment

        if 'attachments' in config['body']:
            for attachment in config['body']['attachments']:
                attachment_template = self.jinja_environment.from_string(
                    attachment)
                attachment_template.name = 'attachment'
                attachment_url = attachment_template.render()
                self.logger.debug('Fetching attachment...',
                                  extra={'attachment': attachment_url})

                filename, content = self._get_attachment(attachment_url)
                if filename:
                    attachment = Attachment()
                    attachment.file_content = base64.b64encode(content).decode()
                    attachment.file_type = 'application/octet-stream'
                    attachment.file_name = filename
                    attachment.disposition = 'attachment'
                    attachment.content_id = filename
                    sendgrid_mail.attachment = attachment

                    self.logger.debug('Attached file.',
                                      extra={
                                          'attachment_filename': filename,
                                          'attachment_size': len(content)
                                      })

        self.logger.debug('Sending email through SendGrid.')
        try:
            response = sg.client.mail.send.post(
                request_body=sendgrid_mail.get())
        except exceptions.BadRequestsError as e:
            self.logger.error('Failed to send via SendGrid (bad request).',
                              extra={'response': e.body})
            raise e
        if response.status_code >= 200 and response.status_code <= 299:
            return True
        return False
Example #19
0
            if not keyword in entry.title:
                if not keyword in get_section(program_html, "番組概要"):
                    if not keyword in get_section(program_html, "人名リンク"):
                        if not keyword in get_section(program_html, "番組詳細"):
                            sys.stderr.write(
                                "[info] skipping %s (no matching keyword)\n" %
                                entry.link)
                            continue

            checked_thistime.append(url_num)
            mes = u"<a href=\"%s\">%s</a> (%s)" % (
                entry.link, html.escape(entry.title), keyword)
            messages.append(mes)

    sess.close()

    if len(messages) > 0:
        message_str = "<br />\n".join(messages)
        sys.stderr.write(u"[info] mailing via sendgrid\n")
        sg_client = sendgrid.SendGridAPIClient(sg_apikey)
        sg_from = sendgrid.Email(name="Check TV Programs", email=sg_username)
        message = sendgrid.Mail(from_email=sg_from,
                                to_emails=[sg_recipient],
                                subject=u"Update of TV Programs",
                                html_content=message_str)
        message.reply_to = sg_recipient
        sg_client.send(message)

    update_sheet(worksheet_checked_previously, checked_thistime)
Example #20
0
def send_email(recipients: list,
               subject: str,
               text: str,
               html: str = '',
               sender: str = '',
               files: list = [],
               exceptions: bool = False):
    """
    :param recipients: List of recipients; or single email (str); or comma-separated email list (str); or list of name-email pairs (e.g. settings.ADMINS)
    :param subject: Subject of the email
    :param text: Body (text)
    :param html: Body (html)
    :param sender: Sender email, or settings.DEFAULT_FROM_EMAIL if missing
    :param files: Paths to files to attach
    :param exceptions: Raise exception if email sending fails
    :return: Status code 202 if all emails were sent successfully, error status code otherwise
    """
    import sendgrid
    from sendgrid.helpers.mail import Content, Mail, Attachment
    from django.conf import settings
    from base64 import b64encode
    from os.path import basename
    from django.utils.timezone import now
    from jutil.logs import log_event

    try:
        # default sender to settings.DEFAULT_FROM_EMAIL
        if not sender:
            sender = settings.DEFAULT_FROM_EMAIL

        # support multiple recipient list styles
        if isinstance(
                recipients,
                str):  # allow single email and comma-separated list as input
            recipients = [str(r).strip() for r in recipients.split(',')]

        sg = sendgrid.SendGridAPIClient(apikey=settings.EMAIL_SENDGRID_API_KEY)
        from_email = sendgrid.Email(sender or settings.DEFAULT_FROM_EMAIL)
        content = Content('text/plain', text) if not html else Content(
            'text/html', html)

        attachments = []
        for filename in files:
            with open(filename, 'rb') as fp:
                attachment = Attachment()
                attachment.content = b64encode(fp.read()).decode()
                attachment.type = "application/octet-stream"
                attachment.filename = basename(filename)
                attachment.content_id = basename(filename)
                attachment.disposition = "attachment"
                attachments.append(attachment)
    except Exception as e:
        logger.error(e)
        if exceptions:
            raise
        return -1

    status_codes = []
    for recipient in recipients:
        try:
            t = now()

            to_email = sendgrid.Email()
            if isinstance(recipient, str):
                to_email.email = recipient
            elif (isinstance(recipient, list)
                  or isinstance(recipient, tuple)) and len(recipient) == 2:
                to_email.name = recipient[0]
                to_email.email = recipient[1]
            else:
                raise Exception(
                    'Invalid recipient format: {}'.format(recipient))

            mail = Mail(from_email=from_email,
                        subject=subject,
                        to_email=to_email,
                        content=content)
            for attachment in attachments:
                mail.add_attachment(attachment)
            res = sg.client.mail.send.post(request_body=mail.get())

            send_dt = (now() - t).total_seconds()
            if res.status_code == 202:
                log_event('EMAIL_SENT',
                          data={
                              'time': send_dt,
                              'to': recipient,
                              'subject': subject,
                              'status': res.status_code
                          })
            else:
                log_event('EMAIL_ERROR',
                          data={
                              'time': send_dt,
                              'to': recipient,
                              'subject': subject,
                              'status': res.status_code,
                              'body': res.body
                          })

            status_codes.append(res.status_code)
        except Exception as e:
            logger.error(e)
            if exceptions:
                raise
            status_codes.append(-1)

    for status in status_codes:
        if status != 202:
            return status
    return 202
Example #21
0
    def output(self):
        mail = {
            'html_body': '',
            'text_body': '',
            'mail_from': '',
            'mail_to': '',
            'mail_subject': '',
        }

        if 'from' not in self.output_config:
            raise NotConfiguredException(
                'No sender (from) configured for email output!')
        if 'to' not in self.output_config:
            raise NotConfiguredException(
                'No recipient (to) configured for email output!')
        if 'subject' not in self.output_config:
            raise NotConfiguredException(
                'No subject configured for email output!')

        if 'body' not in self.output_config:
            raise NotConfiguredException(
                'No body configured for email output!')

        for mail_type in ['html', 'text']:
            if mail_type in self.output_config['body']:
                mail_template = self.jinja_environment.from_string(
                    self.output_config['body'][mail_type])
                mail_template.name = mail_type
                mail['%s_body' % mail_type] = mail_template.render()

        if mail['html_body'] == '' and mail['text_body'] == '':
            raise NotConfiguredException(
                'No HMTL or text email body configured for email output!')

        for tpl in ['from', 'to', 'subject']:
            mail_template = self.jinja_environment.from_string(
                self.output_config[tpl])
            mail['mail_%s' % tpl] = mail_template.render()

        self.logger.debug('Canonicalizing email formats...')
        # Canonicalize the email formats
        for tpl in ['from', 'to']:
            parsed_emails = email.utils.getaddresses([mail['mail_%s' % tpl]])
            if tpl == 'from' and len(parsed_emails) > 1:
                raise MultipleSendersException(
                    'Multiple senders in from field!')
            new_email = ''
            for e in parsed_emails:
                new_email += ', ' if new_email != '' else ''
                new_email += email.utils.formataddr(e)
            mail['mail_%s' % tpl] = new_email

        if 'expandGroupRecipients' in self.output_config and self.output_config[
                'expandGroupRecipients']:

            to_emails = email.utils.getaddresses([mail['mail_to']])
            self.logger.debug('Starting expansion of group recipients...',
                              extra={'to': to_emails})

            service_account = self.output_config[
                'serviceAccountEmail'] if 'serviceAccountEmail' in self.output_config else None
            user_credentials = Credentials(
                self.get_token_for_scopes([
                    'https://www.googleapis.com/auth/admin.directory.user.readonly'
                ],
                                          service_account=service_account))
            group_credentials = Credentials(
                self.get_token_for_scopes([
                    'https://www.googleapis.com/auth/cloud-identity.groups.readonly'
                ],
                                          service_account=service_account))

            user_service = discovery.build('admin',
                                           'directory_v1',
                                           credentials=user_credentials)
            group_service = discovery.build('cloudidentity',
                                            'v1beta1',
                                            credentials=group_credentials)
            new_emails = []
            for e in to_emails:
                request = group_service.groups().lookup()
                request.uri += "&groupKey.id=" + e[1]
                try:
                    response = request.execute()
                except errors.HttpError as exc:
                    if exc.resp.status == 404 or exc.resp.status == 403:
                        self.logger.debug(
                            'Did not find group %s in Cloud Identity.' %
                            (e[1]),
                            extra={'response': exc.resp})
                        response = None
                    else:
                        raise exc
                if response and 'name' in response:
                    m_request = group_service.groups().memberships().list(
                        parent=response['name'])
                    m_response = m_request.execute()
                    if 'memberships' in m_response:  # If this field doesn't exist, it's probably an empty group
                        for membership in m_response['memberships']:
                            new_emails.append(
                                email.utils.formataddr(
                                    ('', membership['memberKey']['id'])))
                else:
                    try:
                        u_response = user_service.users().get(
                            userKey=e[1]).execute()
                        if u_response:
                            new_emails.append(e[1])
                    except errors.HttpError as exc:
                        if not 'ignoreNonexistentGroups' in self.output_config or not self.output_config[
                                'ignoreNonexistentGroups']:
                            raise GroupNotFoundException(
                                'Failed to find group %s in Cloud Identity!' %
                                e[1])
                        elif 'ignoreNonexistentGroups' in self.output_config and isinstance(
                                self.output_config['ignoreNonexistentGroups'],
                                str
                        ) and not e[1].endswith(
                                self.output_config['ignoreNonexistentGroups']):
                            new_emails.append(e[1])
                        else:
                            self.logger.debug('Non-existent user %s skipped.' %
                                              (e[1]),
                                              extra={'response': exc.resp})

            new_to = ''
            for e in new_emails:
                new_to += ', ' if new_to != '' else ''
                new_to += e
            mail['mail_to'] = new_to
            self.logger.debug('Finished expanding group recipients.',
                              extra={'to': new_to})

        if 'transports' not in self.output_config:
            raise NotConfiguredException(
                'No transports configured for sending email.')

        embedded_images = {}
        if 'images' in self.output_config['body']:
            for image in self.output_config['body']['images']:
                image_template = self.jinja_environment.from_string(image)
                image_template.name = 'image'
                image_url = image_template.render()
                self.logger.debug('Fetching attached image...',
                                  extra={'image': image_url})

                image_filename = None
                if image_url.startswith('gs://'):  # Cloud Storage file
                    image_filename, image_content = self._get_attachment(
                        image_url)
                else:
                    if os.path.exists(image_url):  # Local file
                        image_filename = os.path.basename(image_url)
                        image_content = open(image_url, 'rb').read()
                    else:
                        self.logger.error('Could not find image attachment.',
                                          extra={'image': image_url})
                if image_filename:
                    embedded_images[image_filename] = image_content
                    self.logger.debug('Attaching embedded image.',
                                      extra={
                                          'image': image_url,
                                          'image_name': image_filename,
                                          'size': len(image_content)
                                      })

        sent_successfully = False
        for transport in self.output_config['transports']:
            try:
                if transport['type'] == 'smtp':
                    if 'host' not in transport:
                        raise NotConfiguredException(
                            'No host configured for SMTP transport.')

                    port = int(
                        transport['port']) if 'port' in transport else 25
                    self.logger.debug('Trying transport.',
                                      extra={
                                          'host': transport['host'],
                                          'port': port
                                      })

                    server = None
                    if 'verifyCertificate' in transport and transport[
                            'verifyCertificate'] == False:
                        context = ssl._create_unverified_context()
                    else:
                        context = ssl.create_default_context()
                    if 'ssl' in transport and transport['ssl']:
                        self.logger.debug('Using SSL connection for SMTP.')
                        server = smtplib.SMTP_SSL(transport['host'],
                                                  port,
                                                  context=context)
                    else:
                        server = smtplib.SMTP(transport['host'], port)
                        if 'starttls' in transport and transport['starttls']:
                            self.logger.debug('Using STARTTLS for SMTP.')
                            server.starttls(context=context)
                    if 'user' in transport and 'password' in transport:
                        self.logger.debug('Logging into SMTP server.')
                        server.login(transport['user'], transport['password'])

                    message = MIMEMultipart('alternative')
                    message['Subject'] = mail['mail_subject']
                    message['From'] = mail['mail_from']
                    message['To'] = mail['mail_to']

                    if mail['text_body'] != '':
                        text_part = MIMEText(mail['text_body'], 'plain')
                        message.attach(text_part)
                    if mail['html_body'] != '':
                        html_part = MIMEText(mail['html_body'], 'html')
                        message.attach(html_part)

                    if 'attachments' in self.output_config['body']:

                        for attachment in self.output_config['body'][
                                'attachments']:
                            attachment_template = self.jinja_environment.from_string(
                                attachment)
                            attachment_template.name = 'attachment'
                            attachment_url = attachment_template.render()
                            self.logger.debug(
                                'Fetching attachment...',
                                extra={'attachment': attachment_url})

                            filename, content = self._get_attachment(
                                attachment_url)
                            file_part = MIMEBase('application', 'octet-stream')
                            file_part.set_payload(content)
                            encoders.encode_base64(file_part)
                            file_part.add_header(
                                'Content-Disposition',
                                'attachment; filename="%s"' % filename)
                            self.logger.debug('Attached file.',
                                              extra={
                                                  'attachment_filename':
                                                  filename,
                                                  'attachment_size':
                                                  len(content)
                                              })
                            message.attach(file_part)

                    if len(embedded_images) > 0:
                        for file_name, content in embedded_images.items():
                            image = MIMEImage(content)
                            image.add_header('Content-ID', '<%s>' % file_name)
                            image.add_header(
                                'Content-Disposition',
                                'inline; filename="%s"; size="%d";' %
                                (file_name, len(content)))
                            message.attach(image)

                    self.logger.debug('Sending email thru SMTP.')
                    server.sendmail(mail['mail_from'], mail['mail_to'],
                                    message.as_string())

                    server.quit()
                    sent_successfully = True
                    break
                elif transport['type'] == 'sendgrid':
                    api_key = None
                    if 'apiKey' in transport:
                        api_key = transport['apiKey']
                    if os.getenv('SENDGRID_API_KEY'):
                        api_key = os.getenv('SENDGRID_API_KEY')
                    if not api_key:
                        raise NotConfiguredException(
                            'No Sendgrid API key configured!')

                    sg = sendgrid.SendGridAPIClient(api_key=api_key)
                    from_email = sendgrid.Email(mail['mail_from'])
                    to_email = sendgrid.To(mail['mail_to'])
                    text_content = sendgrid.Content('text/plain',
                                                    mail['text_body'])
                    html_content = sendgrid.Content('text/html',
                                                    mail['html_body'])
                    sendgrid_mail = sendgrid.Mail(from_email, to_email,
                                                  mail['mail_subject'],
                                                  text_content)
                    sendgrid_mail.add_content(html_content)
                    if len(embedded_images) > 0:
                        for file_name, content in embedded_images.items():
                            attachment = Attachment()
                            attachment.file_content = base64.b64encode(
                                content).decode()
                            attachment.file_type = 'application/octet-stream'
                            attachment.file_name = file_name
                            attachment.disposition = 'inline'
                            attachment.content_id = file_name
                            sendgrid_mail.attachment = attachment

                    if 'attachments' in self.output_config['body']:
                        for attachment in self.output_config['body'][
                                'attachments']:
                            attachment_template = self.jinja_environment.from_string(
                                attachment)
                            attachment_template.name = 'attachment'
                            attachment_url = attachment_template.render()
                            self.logger.debug(
                                'Fetching attachment...',
                                extra={'attachment': attachment_url})

                            filename, content = self._get_attachment(
                                attachment_url)
                            attachment = Attachment()
                            attachment.file_content = base64.b64encode(
                                content).decode()
                            attachment.file_type = 'application/octet-stream'
                            attachment.file_name = filename
                            attachment.disposition = 'attachment'
                            attachment.content_id = filename
                            sendgrid_mail.attachment = attachment

                            self.logger.debug('Attached file.',
                                              extra={
                                                  'attachment_filename':
                                                  filename,
                                                  'attachment_size':
                                                  len(content)
                                              })

                    self.logger.debug('Sending email through SendGrid.')
                    response = sg.client.mail.send.post(
                        request_body=sendgrid_mail.get())
                    if response.status_code >= 200 and response.status_code <= 299:
                        sent_successfully = True
                        break
                else:
                    self.logger.exception(
                        'Unknown transport type %s in configuration.' %
                        transport['type'])
            except Exception:
                transport_sanitized = transport
                transport_sanitized.pop('apiKey', None)
                transport_sanitized.pop('user', None)
                transport_sanitized.pop('password', None)
                self.logger.exception(
                    'Error when attempting to use transport.',
                    extra={
                        'transport': transport_sanitized,
                        'mail': mail
                    })
        if not sent_successfully:
            self.logger.error(
                'Unable to send email, none of the transports worked.')
        else:
            self.logger.info('Message sent!',
                             extra={
                                 'from': mail['mail_from'],
                                 'to': mail['mail_to'],
                                 'subject': mail['mail_subject']
                             })
Example #22
0
def invoice_cron(request):
    if "SENDGRID_API_KEY" in os.environ:
        pool = ThreadPool(100)

        def create_invoice(member):
            if member.profile.state == "active":
                if member.profile.last_invoice is not None:
                    if member.profile.last_invoice.month == timezone.now(
                    ).month:
                        print("already invoiced this month")
                        return {
                            "name": member.profile.get_full_name(),
                            "email": member.email,
                            "success": False,
                            "message": "User already invoiced this month."
                        }

                    elif member.profile.xero_account_id:
                        return {
                            "name": member.profile.get_full_name(),
                            "email": member.email,
                            "success":
                            member.profile.create_membership_invoice(),
                            "message": ""
                        }

                elif member.profile.xero_account_id:
                    return {
                        "name": member.profile.get_full_name(),
                        "email": member.email,
                        "success": member.profile.create_membership_invoice(),
                        "message": ""
                    }

                return {
                    "name": member.profile.get_full_name(),
                    "email": member.email,
                    "success": False,
                    "message": "No contact in xero."
                }

        results = pool.map(create_invoice, User.objects.all())

        successful = list()
        failed = list()
        successful_string, failed_string = "", ""

        for result in results:
            if result is not None:
                if result['success']:
                    successful.append("{} - {}<br>".format(
                        result['name'], result['email']))
                    successful_string += "{} - {} - {}<br>".format(
                        result['name'], result['email'], result['message'])

                else:
                    failed.append("{} - {} - {}<br>".format(
                        result['name'], result['email'], result['message']))
                    failed_string += "{} - {} - {}<br>".format(
                        result['name'], result['email'], result['message'])

        body = "HSBNE invoice generation ran with {} successful and {} failed.<br>".format(len(successful),
                                                                                           len(failed)) + \
               "Invoice creation for the following members failed: <br>{}<br><br>".format(failed_string) + \
               "Invoice creation for the following members succeeded:<br>{}".format(successful_string)

        sg = sendgrid.SendGridAPIClient(
            apikey=os.environ.get('SENDGRID_API_KEY'))
        from_email = sendgrid.Email(settings.FROM_EMAIL_TREASURER)
        to_email = sendgrid.Email(settings.SYSADMIN_EMAIL)
        subject = "HSBNE invoice generation ran with {} successful and {} failed.".format(
            len(successful), len(failed))
        content = sendgrid.helpers.mail.Content("text/html", body)
        mail = sendgrid.helpers.mail.Mail(from_email, subject, to_email,
                                          content)
        response = sg.client.mail.send.post(request_body=mail.get())

        return HttpResponse(response.status_code)