def test_helloEmail(self):
        self.maxDiff = None

        """Minimum required to send an email"""
        mail = Mail()

        mail.from_email = Email("*****@*****.**")

        mail.subject = "Hello World from the SendGrid Python Library"

        personalization = Personalization()
        personalization.add_to(Email("*****@*****.**"))
        mail.add_personalization(personalization)

        mail.add_content(Content("text/plain", "some text here"))
        mail.add_content(
            Content(
                "text/html",
                "<html><body>some text here</body></html>"))

        self.assertEqual(
            json.dumps(
                mail.get(),
                sort_keys=True),
            '{"content": [{"type": "text/plain", "value": "some text here"}, '
            '{"type": "text/html", '
            '"value": "<html><body>some text here</body></html>"}], '
            '"from": {"email": "*****@*****.**"}, "personalizations": '
            '[{"to": [{"email": "*****@*****.**"}]}], '
            '"subject": "Hello World from the SendGrid Python Library"}'
        )

        self.assertTrue(isinstance(str(mail), str))
    def test_unicode_values_in_substitutions_helper(self):

        """ Test that the Substitutions helper accepts unicode values """

        self.maxDiff = None

        """Minimum required to send an email"""
        mail = Mail()

        mail.from_email = Email("*****@*****.**")

        mail.subject = "Testing unicode substitutions with the SendGrid Python Library"

        personalization = Personalization()
        personalization.add_to(Email("*****@*****.**"))
        personalization.add_substitution(Substitution("%city%", u"Αθήνα"))
        mail.add_personalization(personalization)

        mail.add_content(Content("text/plain", "some text here"))
        mail.add_content(
            Content(
                "text/html",
                "<html><body>some text here</body></html>"))

        expected_result = {
            "content": [
                {
                    "type": "text/plain",
                    "value": "some text here"
                },
                {
                    "type": "text/html",
                    "value": "<html><body>some text here</body></html>"
                }
            ],
            "from": {
                "email": "*****@*****.**"
            },
            "personalizations": [
                {
                    "substitutions": {
                        "%city%": u"Αθήνα"
                    },
                    "to": [
                        {
                            "email": "*****@*****.**"
                        }
                    ]
                }
            ],
            "subject": "Testing unicode substitutions with the SendGrid Python Library",
        }

        self.assertEqual(
            json.dumps(mail.get(), sort_keys=True),
            json.dumps(expected_result, sort_keys=True)
        )
Esempio n. 3
0
def send_email(to, subject, html_content, files=None,
               dryrun=False, cc=None, bcc=None,
               mime_subtype='mixed', **kwargs):
    """
    Send an email with html content using sendgrid.

    To use this plugin:
    0. include sendgrid subpackage as part of your Airflow installation, e.g.,
    pip install airflow[sendgrid]
    1. update [email] backend in airflow.cfg, i.e.,
    [email]
    email_backend = airflow.contrib.utils.sendgrid.send_email
    2. configure Sendgrid specific environment variables at all Airflow instances:
    SENDGRID_MAIL_FROM={your-mail-from}
    SENDGRID_API_KEY={your-sendgrid-api-key}.
    """
    mail = Mail()
    mail.from_email = Email(os.environ.get('SENDGRID_MAIL_FROM'))
    mail.subject = subject

    # Add the recipient list of to emails.
    personalization = Personalization()
    to = get_email_address_list(to)
    for to_address in to:
        personalization.add_to(Email(to_address))
    if cc:
        cc = get_email_address_list(cc)
        for cc_address in cc:
            personalization.add_cc(Email(cc_address))
    if bcc:
        bcc = get_email_address_list(bcc)
        for bcc_address in bcc:
            personalization.add_bcc(Email(bcc_address))
    mail.add_personalization(personalization)
    mail.add_content(Content('text/html', html_content))

    # Add custom_args to personalization if present
    pers_custom_args = kwargs.get('personalization_custom_args', None)
    if isinstance(pers_custom_args, dict):
        for key in pers_custom_args.keys():
            personalization.add_custom_arg(CustomArg(key, pers_custom_args[key]))

    # Add email attachment.
    for fname in files or []:
        basename = os.path.basename(fname)
        attachment = Attachment()
        with open(fname, "rb") as f:
            attachment.content = base64.b64encode(f.read())
            attachment.type = mimetypes.guess_type(basename)[0]
            attachment.filename = basename
            attachment.disposition = "attachment"
            attachment.content_id = '<%s>' % basename
        mail.add_attachment(attachment)
    _post_sendgrid_mail(mail.get())
Esempio n. 4
0
    def _prepare_sendgrid_data(self):
        self.ensure_one()
        s_mail = Mail()
        s_mail.set_from(Email(self.email_from))
        s_mail.set_reply_to(Email(self.reply_to))
        s_mail.add_custom_arg(CustomArg('odoo_id', self.message_id))
        html = self.body_html or ' '

        p = re.compile(r'<.*?>')  # Remove HTML markers
        text_only = self.body_text or p.sub('', html.replace('<br/>', '\n'))

        s_mail.add_content(Content("text/plain", text_only))
        s_mail.add_content(Content("text/html", html))

        test_address = config.get('sendgrid_test_address')

        # TODO For now only one personalization (transactional e-mail)
        personalization = Personalization()
        personalization.set_subject(self.subject or ' ')
        if not test_address:
            if self.email_to:
                personalization.add_to(Email(self.email_to))
            for recipient in self.recipient_ids:
                personalization.add_to(Email(recipient.email))
            if self.email_cc:
                personalization.add_cc(Email(self.email_cc))
        else:
            _logger.info('Sending email to test address {}'.format(
                test_address))
            personalization.add_to(Email(test_address))
            self.email_to = test_address

        if self.sendgrid_template_id:
            s_mail.set_template_id(self.sendgrid_template_id.remote_id)

        for substitution in self.substitution_ids:
            personalization.add_substitution(Substitution(
                substitution.key, substitution.value))

        s_mail.add_personalization(personalization)

        for attachment in self.attachment_ids:
            s_attachment = Attachment()
            # Datas are not encoded properly for sendgrid
            s_attachment.set_content(base64.b64encode(base64.b64decode(
                attachment.datas)))
            s_attachment.set_filename(attachment.name)
            s_mail.add_attachment(s_attachment)

        return s_mail.get()
    def test_sendgrid_api_key(self):
        """Tests if including SendGrid API will throw an Exception"""

        # Minimum required to send an email
        self.max_diff = None
        mail = Mail()

        mail.from_email = Email("*****@*****.**")

        mail.subject = "Hello World from the SendGrid Python Library"

        personalization = Personalization()
        personalization.add_to(Email("*****@*****.**"))
        mail.add_personalization(personalization)

        # Try to include SendGrid API key
        try:
            mail.add_content(
                Content(
                    "text/plain",
                    "some SG.2123b1B.1212lBaC here"))
            mail.add_content(
                Content(
                    "text/html",
                    "<html><body>some SG.Ba2BlJSDba.232Ln2 here</body></html>"))

            self.assertEqual(
                json.dumps(
                    mail.get(),
                    sort_keys=True),
                '{"content": [{"type": "text/plain", "value": "some text here"}, '
                '{"type": "text/html", '
                '"value": "<html><body>some text here</body></html>"}], '
                '"from": {"email": "*****@*****.**"}, "personalizations": '
                '[{"to": [{"email": "*****@*****.**"}]}], '
                '"subject": "Hello World from the SendGrid Python Library"}'
            )

        # Exception should be thrown
        except Exception:
            pass

        # Exception not thrown
        else:
            self.fail("Should have failed as SendGrid API key included")
Esempio n. 6
0
File: mails.py Progetto: nau101/web
def send_mail(from_email, to_email, subject, body, html=False, from_name="Gitcoin.co", cc_emails=None):

    # make sure this subscriber is saved
    get_or_save_email_subscriber(to_email, 'internal')

    # debug logs
    print("-- Sending Mail '{}' to {}".format(subject, to_email))

    # setup
    sg = sendgrid.SendGridAPIClient(apikey=settings.SENDGRID_API_KEY)
    from_email = Email(from_email, from_name)
    to_email = Email(to_email)
    contenttype = "text/plain" if not html else "text/html"

    # build content
    content = Content(contenttype, html) if html else Content(contenttype, body)
    if settings.DEBUG:
        to_email = Email(settings.CONTACT_EMAIL) #just to be double secret sure of what were doing in dev
        subject = "[DEBUG] " + subject
    mail = Mail(from_email, subject, to_email, content)

    # build personalization (BCC + CC)
    p = Personalization()
    p.add_to(to_email)
    if cc_emails: #only add CCif not in prod
        for cc_addr in set(cc_emails):
            cc_addr = Email(cc_addr)
            if settings.DEBUG:
                cc_addr = to_email
            if cc_addr._email != to_email._email:
                p.add_to(cc_addr)
    p.add_bcc(Email(settings.BCC_EMAIL))
    mail.add_personalization(p)

    # send mails
    response = sg.client.mail.send.post(request_body=mail.get())
    return response
Esempio n. 7
0
    def _create_email(self, email: dict, email_id: str) -> Mail:
        self.log_debug('converting email %s to sendgrid format', email_id)
        mail = Mail()
        personalization = Personalization()

        for i, to in enumerate(email.get('to', [])):
            personalization.add_to(Email(to))
            self.log_debug('added to %d to email %s', i, email_id)

        for i, cc in enumerate(email.get('cc', [])):
            personalization.add_cc(Email(cc))
            self.log_debug('added cc %d to email %s', i, email_id)

        for i, bcc in enumerate(email.get('bcc', [])):
            personalization.add_bcc(Email(bcc))
            self.log_debug('added bcc %d to email %s', i, email_id)

        mail.add_personalization(personalization)
        self.log_debug('added recipients to email %s', email_id)

        mail.subject = email.get('subject', '(no subject)')
        self.log_debug('added subject to email %s', email_id)

        mail.add_content(
            Content('text/html', email.get('body', '(no content)')))
        self.log_debug('added content to email %s', email_id)

        mail.from_email = Email(email.get('from'))
        self.log_debug('added from to email %s', email_id)

        for i, attachment in enumerate(email.get('attachments', [])):
            mail.add_attachment(self._create_attachment(attachment))
            self.log_debug('added attachment %d to email %s', i, email_id)

        self.log_debug('converted email %s to sendgrid format', email_id)
        return mail
Esempio n. 8
0
    def send_email(self,
                   subject,
                   message,
                   recipient,
                   attachments=None,
                   ismultiple=False):
        mail = Mail(
            from_email="*****@*****.**",
            html_content=message,
            subject=subject,
        )

        personalize = Personalization()

        if ismultiple:
            for email in recipient:
                #add_bcc isn't working right now, and there doesn't seem to be a straightforward workaround
                #will now work if any of the emails in recipient list is invalid
                personalize.add_to(Email(email))
        else:
            personalize.add_to(Email(recipient))

        mail.add_personalization(personalize)

        if attachments:
            encoded_file = base64.b64encode(attachments).decode()
            attachedFile = Attachment(FileContent(encoded_file),
                                      FileName('event.ics'),
                                      FileType('ical/ics'),
                                      Disposition('attachment'))
            mail.attachment = attachedFile

        try:
            response = self.client.mail.send.post(request_body=mail.get())
        except Exception as e:
            print(e.message)
Esempio n. 9
0
def send_email_sendgrid(to,
                        subject,
                        html_content,
                        files=None,
                        dryrun=False,
                        cc=None,
                        bcc=None,
                        mime_subtype='mixed'):
    """
    Send an email with html content using sendgrid.
    """
    mail = Mail()
    mail.from_email = Email(configuration.get('sendgrid',
                                              'SENDGRID_MAIL_FROM'))
    mail.subject = subject

    # Add the list of to emails.
    to = get_email_address_list(to)
    personalization = Personalization()
    for to_address in to:
        personalization.add_to(Email(to_address))
    mail.add_personalization(personalization)
    mail.add_content(Content('text/html', html_content))

    # Add email attachment.
    for fname in files or []:
        basename = os.path.basename(fname)
        attachment = Attachment()
        with open(fname, "rb") as f:
            attachment.content = base64.b64encode(f.read())
            attachment.type = mimetypes.guess_type(basename)[0]
            attachment.filename = basename
            attachment.disposition = "attachment"
            attachment.content_id = '<%s>' % basename
        mail.add_attachment(attachment)
    _post_sendgrid_mail(mail.get())
Esempio n. 10
0
    def _prepare_email_message(self):
        """Prepare email message for Sendgrid

        :return: Sendgrid Email message
        """
        mail = Mail()

        mail.from_email = Email(self.source)
        mail.subject = self.subject

        # personalization of email
        personalization = Personalization()

        # add multiple recipients
        for to_email in self._convert_var_type_to_list(self.destination):
            personalization.add_to(Email(to_email))
            mail.add_personalization(personalization)

        # add cc (if any)
        if self.cc:
            for cc_email in self._convert_var_type_to_list(self.cc):
                personalization.add_cc(Email(cc_email))
                mail.add_personalization(personalization)

        # add bcc (if any)
        if self.bcc:
            for bcc_email in self._convert_var_type_to_list(self.bcc):
                personalization.add_bcc(Email(bcc_email))
                mail.add_personalization(personalization)

        # add content of email
        if self.body:
            mail.add_content(Content('text/plain', self.body))
        if self.html_message:
            mail.add_content(Content('text/html', self.html_message))

        # add attachments
        if self.attachment:
            mail.add_attachment(self.attachment)

        return mail.get()
Esempio n. 11
0
    def _build_sg_mail(self, email):
        mail = Mail()
        from_name, from_email = rfc822.parseaddr(email.from_email)
        # Python sendgrid client should improve
        # sendgrid/helpers/mail/mail.py:164
        if not from_name:
            from_name = None
        mail.set_from(Email(from_email, from_name))
        mail.set_subject(email.subject)

        personalization = Personalization()
        for e in email.to:
            personalization.add_to(Email(e))
        for e in email.cc:
            personalization.add_cc(Email(e))
        for e in email.bcc:
            personalization.add_bcc(Email(e))
        personalization.set_subject(email.subject)
        mail.add_content(Content("text/plain", email.body))
        if isinstance(email, EmailMultiAlternatives):
            for alt in email.alternatives:
                if alt[1] == "text/html":
                    mail.add_content(Content(alt[1], alt[0]))
        elif email.content_subtype == "html":
            mail.contents = []
            mail.add_content(Content("text/plain", ' '))
            mail.add_content(Content("text/html", email.body))

        if hasattr(email, 'categories'):
            for c in email.categories:
                mail.add_category(Category(c))

        if hasattr(email, 'custom_args'):
            for k, v in email.custom_args.items():
                mail.add_custom_arg(CustomArg(k, v))

        if hasattr(email, 'template_id'):
            mail.set_template_id(email.template_id)
            if hasattr(email, 'substitutions'):
                for key, value in email.substitutions.items():
                    personalization.add_substitution(Substitution(key, value))

        # SendGrid does not support adding Reply-To as an extra
        # header, so it needs to be manually removed if it exists.
        reply_to_string = ""
        for key, value in email.extra_headers.items():
            if key.lower() == "reply-to":
                reply_to_string = value
            else:
                mail.add_header({key: value})
        # Note that if you set a "Reply-To" header *and* the reply_to
        # attribute, the header's value will be used.
        if not mail.reply_to and hasattr(email, "reply_to") and email.reply_to:
            # SendGrid only supports setting Reply-To to a single address.
            # See https://github.com/sendgrid/sendgrid-csharp/issues/339.
            reply_to_string = email.reply_to[0]
        # Determine whether reply_to contains a name and email address, or
        # just an email address.
        if reply_to_string:
            reply_to_name, reply_to_email = rfc822.parseaddr(reply_to_string)
            if reply_to_name and reply_to_email:
                mail.set_reply_to(Email(reply_to_email, reply_to_name))
            elif reply_to_email:
                mail.set_reply_to(Email(reply_to_email))

        for attachment in email.attachments:
            if isinstance(attachment, MIMEBase):
                attach = Attachment()
                attach.set_filename(attachment.get_filename())
                attach.set_content(base64.b64encode(attachment.get_payload()))
                mail.add_attachment(attach)
            elif isinstance(attachment, tuple):
                attach = Attachment()
                attach.set_filename(attachment[0])
                base64_attachment = base64.b64encode(attachment[1])
                if sys.version_info >= (3,):
                    attach.set_content(str(base64_attachment, 'utf-8'))
                else:
                    attach.set_content(base64_attachment)
                attach.set_type(attachment[2])
                mail.add_attachment(attach)

        mail.add_personalization(personalization)
        return mail.get()
def notify(data,
           to,
           template_id=None,
           subject_template="N/A",
           body_template="N/A",
           sender=SENDGRID_SENDER,
           debug_options=None):
    if isinstance(to, basestring):
        raise Exception("Expected list in 'to'")

    apikey = get_sendgrid_api_key()
    if not apikey:
        logging.warn("%s is not set in config. Not sending emails" %
                     CONFIG_APIKEY)
        return

    sg = sendgrid.SendGridAPIClient(apikey=apikey)

    subject = subject_template.format(**data)
    content = Content('text/html', body_template.format(**data))

    mail = Mail()
    mail.set_from(sender)
    mail.set_subject(subject)
    mail.add_content(content)
    personalization = Personalization()

    for address in to:
        personalization.add_to(Email(address))

    if template_id:
        ## flatten the data dict, adding prefix to nested dicts
        for key, value in data.iteritems():
            if isinstance(value, dict):
                for key2, value2 in value.iteritems():
                    placeholder = "-%s__%s-" % (key, key2)
                    personalization.add_substitution(
                        Substitution(placeholder, value2))

            else:
                placeholder = "-%s-" % key
                personalization.add_substitution(
                    Substitution(placeholder, value))

        mail.set_template_id(template_id)

    mail.add_personalization(personalization)

    no_emails = False
    if debug_options:
        for option in debug_options.split(","):
            if option == "noEmails":
                no_emails = True

    if no_emails:
        logging.info("noEmails debug option set, not sending email: %s" %
                     mail.get())

    else:
        response = sg.client.mail.send.post(request_body=mail.get())

        logging.debug(response.status_code)
        logging.debug(response.body)
        logging.debug(response.headers)
Esempio n. 13
0
def send_pdf_email_using_SendGrid(sender,
                                  receiver,
                                  mail_subject,
                                  mail_content,
                                  pdf_attachment,
                                  txt_attachment=None,
                                  cc_email=None):

    # Where it was uploaded Path.
    file_path = pdf_attachment

    with open(file_path, 'rb') as f:
        data = f.read()

    # Encode contents of file as Base 64
    encoded = base64.b64encode(data).decode()
    """Build PDF attachment"""
    attachment = Attachment()
    attachment.file_content = FileContent(encoded)
    attachment.file_type = FileType('application/pdf')
    attachment.file_name = FileName('your_quote.pdf')
    attachment.disposition = Disposition('attachment')
    attachment.content_id = ContentId('Example Content ID')
    """ Add txt file """
    if txt_attachment:
        file_path = txt_attachment

        with open(file_path, 'rb') as f:
            data = f.read()

        # Encode contents of file as Base 64
        encoded = base64.b64encode(data).decode()
        """Build txt attachment"""
        attachment2 = Attachment()
        attachment2.file_content = FileContent(encoded)
        attachment2.file_type = FileType('text/html')
        attachment2.file_name = FileName('quote.txt')
        attachment2.disposition = Disposition('attachment')
        attachment2.content_id = ContentId('Text Example Content ID')

    message = Mail(
        from_email=sender,
        #to_emails = receiver,			# Removed since it generates an extra email with SendGrid
        subject=mail_subject,
        html_content=mail_content)
    message.attachment = attachment

    if cc_email:
        cc = Email(cc_email)
        to = Email(receiver)
        p = Personalization()
        p.add_to(to)
        p.add_cc(cc)
        message.add_personalization(p)
    else:  # no cc
        to = Email(receiver)
        p = Personalization()
        p.add_to(to)
        message.add_personalization(p)
    if txt_attachment:
        message.add_attachment(attachment2)

    try:
        sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
        response = sg.send(message)
        print(response.status_code)
        print(response.body)
        print(response.headers)
    except Exception as e:
        print(e.message)

    return
Esempio n. 14
0
    def _build_sg_mail(self, msg):
        mail = Mail()

        mail.from_email = Email(*self._parse_email_address(msg.from_email))
        mail.subject = msg.subject

        personalization = Personalization()
        for addr in msg.to:
            personalization.add_to(Email(*self._parse_email_address(addr)))

        for addr in msg.cc:
            personalization.add_cc(Email(*self._parse_email_address(addr)))

        for addr in msg.bcc:
            personalization.add_bcc(Email(*self._parse_email_address(addr)))

        personalization.subject = msg.subject

        for k, v in msg.extra_headers.items():
            if k.lower() == "reply-to":
                mail.reply_to = Email(v)
            else:
                personalization.add_header(Header(k, v))

        if hasattr(msg, "template_id"):
            mail.template_id = msg.template_id
            if hasattr(msg, "substitutions"):
                for k, v in msg.substitutions.items():
                    personalization.add_substitution(Substitution(k, v))

        mail.add_personalization(personalization)

        if hasattr(msg, "reply_to") and msg.reply_to:
            if mail.reply_to:
                # If this code path is triggered, the reply_to on the sg mail was set in a header above
                reply_to = Email(*self._parse_email_address(msg.reply_to))
                if reply_to.email != mail.reply_to.email or reply_to.name != mail.reply_to.name:
                    raise ValueError("Sendgrid only allows 1 email in the reply-to field.  " +
                                     "Reply-To header value != reply_to property value.")

            if not isinstance(msg.reply_to, basestring):
                if len(msg.reply_to) > 1:
                    raise ValueError("Sendgrid only allows 1 email in the reply-to field")
                mail.reply_to = Email(*self._parse_email_address(msg.reply_to[0]))
            else:
                mail.reply_to = Email(*self._parse_email_address(msg.reply_to))

        for attch in msg.attachments:
            attachment = Attachment()

            if isinstance(attch, MIMEBase):
                filename = attch.get_filename()
                if not filename:
                    ext = mimetypes.guess_extension(attch.get_content_type())
                    filename = "part-{0}{1}".format(uuid.uuid4().hex, ext)
                attachment.filename = filename
                # todo: Read content if stream?
                attachment.content = attch.get_payload().replace("\n", "")
                attachment.type = attch.get_content_type()
                content_id = attch.get("Content-ID")
                if content_id:
                    attachment.content_id = content_id
                    attachment.disposition = "inline"

            else:
                filename, content, mimetype = attch

                attachment.filename = filename
                # todo: Read content if stream?
                attachment.content = base64.b64encode(content)
                attachment.type = mimetype

            mail.add_attachment(attachment)

        if isinstance(msg, EmailMultiAlternatives):
            mail.add_content(Content("text/plain", msg.body))
            for alt in msg.alternatives:
                if alt[1] == "text/html":
                    mail.add_content(Content(alt[1], alt[0]))
        elif msg.content_subtype == "html":
            mail.add_content(Content("text/plain", " "))
            mail.add_content(Content("text/html", msg.body))
        else:
            mail.add_content(Content("text/plain", msg.body))

        if hasattr(msg, "categories"):
            for cat in msg.categories:
                mail.add_category(Category(cat))

        mail_settings = MailSettings()
        mail_settings.sandbox_mode = SandBoxMode(self.sandbox_mode)
        mail.mail_settings = mail_settings

        tracking_settings = TrackingSettings()
        tracking_settings.open_tracking = OpenTracking(self.track_email)
        mail.tracking_settings = tracking_settings

        return mail.get()
Esempio n. 15
0
    def _build_sg_mail(self, msg: EmailMessage) -> Dict:
        """
        Serializes a Django EmailMessage into its JSON representation.

        Returns a Dict of mail data to be consumed by the sendgrid api.
        """
        mail = Mail()

        mail.from_email = Email(*self._parse_email_address(msg.from_email))

        personalization_headers = []
        for k, v in msg.extra_headers.items():
            if k.lower() == "reply-to":
                mail.reply_to = Email(v)
            else:
                personalization_headers.append(Header(k, v))

        if hasattr(msg, "ip_pool_name"):
            if not isinstance(msg.ip_pool_name, str):
                raise ValueError(
                    "ip_pool_name must be a str, got: {}; ".format(
                        type(msg.ip_pool_name)))

            # Validate ip_pool_name length before attempting to add
            if not 2 <= len(msg.ip_pool_name) <= 64:
                raise ValueError(
                    "the number of characters of ip_pool_name must be min 2 and max 64, got: {}; "
                    "see https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/"
                    "index.html#-Request-Body-Parameters".format(
                        len(msg.ip_pool_name)))

            if SENDGRID_5:
                ip_pool_name = msg.ip_pool_name
            else:
                ip_pool_name = IpPoolName(msg.ip_pool_name)
            mail.ip_pool_name = ip_pool_name

        if hasattr(msg, "reply_to") and msg.reply_to:
            if mail.reply_to:
                # If this code path is triggered, the reply_to on the sg mail was set in a header above
                reply_to = Email(*self._parse_email_address(msg.reply_to[0]))
                if (reply_to.email != mail.reply_to.email
                        or reply_to.name != mail.reply_to.name):
                    raise ValueError(
                        "Sendgrid only allows 1 email in the reply-to field.  "
                        + "Reply-To header value != reply_to property value.")

            if not isinstance(msg.reply_to, str):
                if len(msg.reply_to) > 1:
                    raise ValueError(
                        "Sendgrid only allows 1 email in the reply-to field")
                mail.reply_to = Email(
                    *self._parse_email_address(msg.reply_to[0]))
            else:
                mail.reply_to = Email(*self._parse_email_address(msg.reply_to))

        for attch in msg.attachments:
            sg_attch = self._create_sg_attachment(attch)
            mail.add_attachment(sg_attch)

        if self._is_transaction_template(msg):
            if msg.body:
                logger.warning(
                    "Message body is ignored in transactional template")
        else:
            msg.body = " " if msg.body == "" else msg.body

        if hasattr(msg, "template_id"):
            # Template mails should not have subject and content attributes
            mail.template_id = msg.template_id

        if not self._is_transaction_template(msg):
            # In sendgrid v6 we should not specify subject and content between request parameter
            # when we are sending a request for a transactional template
            mail.subject = msg.subject
            if isinstance(msg, EmailMultiAlternatives):
                mail.add_content(Content("text/plain", msg.body))
                for alt in msg.alternatives:
                    if alt[1] == "text/html":
                        mail.add_content(Content(alt[1], alt[0]))
            elif msg.content_subtype == "html":
                mail.add_content(Content("text/plain", " "))
                mail.add_content(Content("text/html", msg.body))
            else:
                mail.add_content(Content("text/plain", msg.body))

        if hasattr(msg, "personalizations"):
            for personalization in msg.personalizations:
                if type(personalization) == Dict:
                    personalization = dict_to_personalization(personalization)

                assert type(personalization) == Personalization

                mail.add_personalization(
                    self._build_sg_personalization(
                        msg,
                        personalization_headers,
                        existing_personalizations=personalization,
                    ))
        elif getattr(msg, "make_private", False):
            for to in msg.to:
                mail.add_personalization(
                    self._build_sg_personalization(
                        msg,
                        personalization_headers,
                        to=[to],
                    ))
        else:
            mail.add_personalization(
                self._build_sg_personalization(
                    msg,
                    personalization_headers,
                    to=msg.to,
                ))

        if hasattr(msg, "categories"):
            for cat in msg.categories:
                mail.add_category(Category(cat))

        if hasattr(msg, "asm"):
            if "group_id" not in msg.asm:
                raise KeyError("group_id not found in asm")

            if "groups_to_display" in msg.asm:
                mail.asm = ASM(msg.asm["group_id"],
                               msg.asm["groups_to_display"])
            else:
                mail.asm = ASM(msg.asm["group_id"])

        mail_settings = MailSettings()
        mail_settings.sandbox_mode = SandBoxMode(self.sandbox_mode)
        mail.mail_settings = mail_settings

        # Handle email tracking
        tracking_settings = getattr(msg, "tracking_settings", None)
        if not isinstance(tracking_settings, TrackingSettings):
            tracking_settings = TrackingSettings()

        if tracking_settings.open_tracking is None:
            tracking_settings.open_tracking = OpenTracking(self.track_email)

        if tracking_settings.click_tracking is None:
            tracking_settings.click_tracking = ClickTracking(
                self.track_clicks_html, self.track_clicks_plain)

        mail.tracking_settings = tracking_settings

        return mail.get()
Esempio n. 16
0
    def _build_sg_mail(self, email):
        mail = Mail()
        from_name, from_email = rfc822.parseaddr(email.from_email)
        # Python sendgrid client should improve
        # sendgrid/helpers/mail/mail.py:164
        if not from_name:
            from_name = None
        mail.from_email = Email(from_email, from_name)
        mail.subject = email.subject

        mail_settings = MailSettings()

        personalization = Personalization()
        for e in email.to:
            personalization.add_to(Email(e))
        for e in email.cc:
            personalization.add_cc(Email(e))
        for e in email.bcc:
            personalization.add_bcc(Email(e))
        personalization.subject = email.subject
        if email.content_subtype == "html":
            mail.add_content(Content("text/html", email.body))
        else:
            mail.add_content(Content("text/plain", email.body))
        if isinstance(email, EmailMultiAlternatives):
            for alt in email.alternatives:
                if alt[1] == "text/html":
                    mail.add_content(Content(alt[1], alt[0]))
        elif email.content_subtype == "html":
            mail.contents = []
            mail.add_content(Content("text/plain", ' '))

        if hasattr(email, 'categories'):
            for c in email.categories:
                mail.add_category(Category(c))

        if hasattr(email, 'custom_args'):
            for k, v in email.custom_args.items():
                mail.add_custom_arg(CustomArg(k, v))

        # Used to override the list management (password reset etc)
        if hasattr(email, 'bypass_list_management'):
            mail_settings.bypass_list_management = BypassListManagement(
                email.bypass_list_management)

        #Check for sandbox mode
        sandbox_mode = getattr(settings, "SENDGRID_SANDBOX", False)
        if sandbox_mode:
            sandbox_whitelist_domains = getattr(
                settings, "SENDGRID_SANDBOX_WHITELIST_DOMAINS", [])
            sandbox_whitelist = False
            for e in email.to:
                domain = e.split('@')[1]
                if domain in sandbox_whitelist_domains:
                    sandbox_whitelist = True

            if not sandbox_whitelist:
                mail_settings.sandbox_mode = SandBoxMode(sandbox_mode)

        if hasattr(email, 'template_id'):
            mail.template_id = email.template_id
            # Version 3 dynamic data  handle bars {{name}}
            if hasattr(email, 'dynamic_data'):
                personalization.dynamic_template_data = email.dynamic_data
            # Version 3 substitutions
            if hasattr(email, 'substitutions'):
                for key, value in email.substitutions.items():
                    personalization.add_substitution(Substitution(key, value))

        # SendGrid does not support adding Reply-To as an extra
        # header, so it needs to be manually removed if it exists.
        reply_to_string = ""
        for key, value in email.extra_headers.items():
            if key.lower() == "reply-to":
                reply_to_string = value
            else:
                mail.add_header({key: value})
        # Note that if you set a "Reply-To" header *and* the reply_to
        # attribute, the header's value will be used.
        if not mail.reply_to and hasattr(email, "reply_to") and email.reply_to:
            # SendGrid only supports setting Reply-To to a single address.
            # See https://github.com/sendgrid/sendgrid-csharp/issues/339.
            reply_to_string = email.reply_to[0]
        # Determine whether reply_to contains a name and email address, or
        # just an email address.
        if reply_to_string:
            reply_to_name, reply_to_email = rfc822.parseaddr(reply_to_string)
            if reply_to_name and reply_to_email:
                mail.reply_to = Email(reply_to_email, reply_to_name)
            elif reply_to_email:
                mail.reply_to = Email(reply_to_email)

        for attachment in email.attachments:
            if isinstance(attachment, MIMEBase):
                attach = Attachment()
                attach.filename = attachment.get_filename()
                attach.content = base64.b64encode(attachment.get_payload())
                mail.add_attachment(attach)
            elif isinstance(attachment, tuple):
                attach = Attachment()
                attach.filename = attachment[0]
                base64_attachment = base64.b64encode(attachment[1])
                if sys.version_info >= (3, ):
                    attach.content = str(base64_attachment, 'utf-8')
                else:
                    attach.content = base64_attachment
                attach.type = attachment[2]
                mail.add_attachment(attach)

        mail.add_personalization(personalization)
        mail.mail_settings = mail_settings
        return mail.get()
Esempio n. 17
0
def send_email(to, subject, html_content, files=None, dryrun=False, cc=None,
               bcc=None, mime_subtype='mixed', sandbox_mode=False, **kwargs):
    """
    Send an email with html content using sendgrid.

    To use this plugin:
    0. include sendgrid subpackage as part of your Airflow installation, e.g.,
    pip install 'apache-airflow[sendgrid]'
    1. update [email] backend in airflow.cfg, i.e.,
    [email]
    email_backend = airflow.contrib.utils.sendgrid.send_email
    2. configure Sendgrid specific environment variables at all Airflow instances:
    SENDGRID_MAIL_FROM={your-mail-from}
    SENDGRID_API_KEY={your-sendgrid-api-key}.
    """
    if files is None:
        files = []

    mail = Mail()
    from_email = kwargs.get('from_email') or os.environ.get('SENDGRID_MAIL_FROM')
    from_name = kwargs.get('from_name') or os.environ.get('SENDGRID_MAIL_SENDER')
    mail.from_email = Email(from_email, from_name)
    mail.subject = subject
    mail.mail_settings = MailSettings()

    if sandbox_mode:
        mail.mail_settings.sandbox_mode = SandBoxMode(enable=True)

    # Add the recipient list of to emails.
    personalization = Personalization()
    to = get_email_address_list(to)
    for to_address in to:
        personalization.add_to(Email(to_address))
    if cc:
        cc = get_email_address_list(cc)
        for cc_address in cc:
            personalization.add_cc(Email(cc_address))
    if bcc:
        bcc = get_email_address_list(bcc)
        for bcc_address in bcc:
            personalization.add_bcc(Email(bcc_address))

    # Add custom_args to personalization if present
    pers_custom_args = kwargs.get('personalization_custom_args', None)
    if isinstance(pers_custom_args, dict):
        for key in pers_custom_args.keys():
            personalization.add_custom_arg(CustomArg(key, pers_custom_args[key]))

    mail.add_personalization(personalization)
    mail.add_content(Content('text/html', html_content))

    categories = kwargs.get('categories', [])
    for cat in categories:
        mail.add_category(Category(cat))

    # Add email attachment.
    for fname in files:
        basename = os.path.basename(fname)

        attachment = Attachment()
        attachment.type = mimetypes.guess_type(basename)[0]
        attachment.filename = basename
        attachment.disposition = "attachment"
        attachment.content_id = '<{0}>'.format(basename)

        with open(fname, "rb") as f:
            attachment.content = base64.b64encode(f.read()).decode('utf-8')

        mail.add_attachment(attachment)
    _post_sendgrid_mail(mail.get())
Esempio n. 18
0
def send_email(to,
               subject,
               html_content,
               files=None,
               dryrun=False,
               cc=None,
               bcc=None,
               mime_subtype='mixed',
               sandbox_mode=False,
               **kwargs):
    """
    Send an email with html content using sendgrid.

    To use this plugin:
    0. include sendgrid subpackage as part of your Airflow installation, e.g.,
    pip install 'apache-airflow[sendgrid]'
    1. update [email] backend in airflow.cfg, i.e.,
    [email]
    email_backend = airflow.contrib.utils.sendgrid.send_email
    2. configure Sendgrid specific environment variables at all Airflow instances:
    SENDGRID_MAIL_FROM={your-mail-from}
    SENDGRID_API_KEY={your-sendgrid-api-key}.
    """
    if files is None:
        files = []

    mail = Mail()
    from_email = kwargs.get('from_email') or os.environ.get(
        'SENDGRID_MAIL_FROM')
    from_name = kwargs.get('from_name') or os.environ.get(
        'SENDGRID_MAIL_SENDER')
    mail.from_email = Email(from_email, from_name)
    mail.subject = subject
    mail.mail_settings = MailSettings()

    if sandbox_mode:
        mail.mail_settings.sandbox_mode = SandBoxMode(enable=True)

    # Add the recipient list of to emails.
    personalization = Personalization()
    to = get_email_address_list(to)
    for to_address in to:
        personalization.add_to(Email(to_address))
    if cc:
        cc = get_email_address_list(cc)
        for cc_address in cc:
            personalization.add_cc(Email(cc_address))
    if bcc:
        bcc = get_email_address_list(bcc)
        for bcc_address in bcc:
            personalization.add_bcc(Email(bcc_address))

    # Add custom_args to personalization if present
    pers_custom_args = kwargs.get('personalization_custom_args', None)
    if isinstance(pers_custom_args, dict):
        for key in pers_custom_args.keys():
            personalization.add_custom_arg(
                CustomArg(key, pers_custom_args[key]))

    mail.add_personalization(personalization)
    mail.add_content(Content('text/html', html_content))

    categories = kwargs.get('categories', [])
    for cat in categories:
        mail.add_category(Category(cat))

    # Add email attachment.
    for fname in files:
        basename = os.path.basename(fname)

        attachment = Attachment()
        attachment.type = mimetypes.guess_type(basename)[0]
        attachment.filename = basename
        attachment.disposition = "attachment"
        attachment.content_id = '<{0}>'.format(basename)

        with open(fname, "rb") as file:
            attachment.content = base64.b64encode(file.read()).decode('utf-8')

        mail.add_attachment(attachment)
    _post_sendgrid_mail(mail.get())
Esempio n. 19
0
class EmailClient(object):
    def __init__(self, empresa_id):
        try:
            self.empresa_id = empresa_id
            # llamar las configuraciones en la DB
            self.email_config = SendgridConf.get_sg_config(self.empresa_id)
            # crear los atributos de la instancia de SendGrid
            self.sg = SendGridAPIClient(api_key=self.email_config.api_key)
            # build message
            self.message = Mail()
            self.message.from_email = Email(self.email_config.asunto_email_dte,
                                            self.email_config.nombre_email_dte)
            # set personalization
            self.personalization = Personalization()
            logger.info("Se instanció EmailClient para la empresa : " +
                        empresa_id)
        except Exception as e:
            logger.error("Error al instanciar EmailClient")
            logger.error(e)
            raise Exception(e)

    def enviar_correo_dte(self, correo):
        try:
            # valores de envío
            self.personalization.add_to(
                Email(correo.correo, correo.nombre_cliente))
            self.message.subject = correo.asunto
            self.message.add_content(Content("text/html", correo.html))
            # valores personalizados
            self.personalization.add_custom_arg(
                CustomArg('email_id', str(correo.id)))
            self.personalization.add_custom_arg(
                CustomArg('empresa', correo.empresa.rut))
            self.personalization.add_custom_arg(
                CustomArg('rut_receptor', correo.rut_receptor))
            self.personalization.add_custom_arg(
                CustomArg('rut_emisor', correo.rut_emisor))
            self.personalization.add_custom_arg(
                CustomArg('tipo_envio', correo.tipo_envio))
            self.personalization.add_custom_arg(
                CustomArg('tipo_dte', str(correo.tipo_dte.id_documento)))
            self.personalization.add_custom_arg(
                CustomArg('numero_folio', str(correo.numero_folio)))
            self.personalization.add_custom_arg(
                CustomArg('resolucion_receptor',
                          str(correo.resolucion_receptor)))
            self.personalization.add_custom_arg(
                CustomArg('resolucion_emisor', str(correo.resolucion_emisor)))
            self.personalization.add_custom_arg(
                CustomArg('monto', str(correo.monto)))
            self.personalization.add_custom_arg(
                CustomArg('fecha_emision', str(correo.fecha_emision)))
            self.personalization.add_custom_arg(
                CustomArg('fecha_recepcion', str(correo.fecha_recepcion)))
            self.personalization.add_custom_arg(
                CustomArg('estado_documento', correo.estado_documento))
            self.personalization.add_custom_arg(
                CustomArg('tipo_operacion', correo.tipo_operacion))
            self.personalization.add_custom_arg(
                CustomArg('tipo_receptor', correo.tipo_receptor))
            self.personalization.add_custom_arg(
                CustomArg('id_envio', str(correo.id_envio)))

            logger.info(correo)

            if correo.xml:
                attach = Attachment()
                attach.filename = get_file_name_from_storage(correo.xml.name)
                attach.content = base64.b64encode(correo.xml.file.read())
                self.message.add_attachment(attach)
            if correo.pdf:
                attach = Attachment()
                attach.filename = get_file_name_from_storage(correo.pdf.name)
                attach.content = base64.b64encode(correo.pdf.file.read())
                self.message.add_attachment(attach)
            if correo.adjunto1:
                attach = Attachment()
                attach.filename = get_file_name_from_storage(
                    correo.adjunto1.name)
                attach.content = base64.b64encode(correo.adjunto1.file.read())
                self.message.add_attachment(attach)
            self.message.add_personalization(self.personalization)
            # enviando el mail
            response = self.sg.client.mail.send.post(
                request_body=self.message.get())
            # imprimiendo respuesta
            logger.info(response.status_code)
            logger.info(response.headers)
            logger.info(response.body)
        except Exception as e:
            logger.error("Error EmailClient.enviar_correo_dte ")
            logger.error(e)
            raise Exception(e)

    def send_report_to_user_with_attach(self, user_email, report):
        try:
            # parametros de correo reporte
            self.message.from_email = Email(
                self.email_config.asunto_email_reporte,
                self.email_config.nombre_email_reporte)
            # buscar usuario
            template_config = TemplateReporte.get_configuration(
                self.empresa_id)
            # preparar template del correo reporte
            user = User.objects.get(email=user_email)
            html = str(template_config.template_html).format(
                user_name=user.first_name)
            # valores de envío
            self.personalization.add_to(Email(user_email, user.first_name))
            self.message.subject = template_config.asunto_reporte
            self.message.add_content(Content("text/html", html))
            # adjuntar excel si esta
            if report['report']:
                attach = Attachment()
                attach.content = base64.b64encode(report['report'])
                attach.filename = report['name']
                self.message.add_attachment(attach)
            self.message.add_personalization(self.personalization)
            # enviando el correo
            response = self.sg.client.mail.send.post(
                request_body=self.message.get())
            # imprimiendo respuesta
            logger.info(response)
            logger.info(response.status_code)
            logger.info(response.headers)
            logger.info(response.body)
        except Exception as e:
            logger.error(
                "Error en EmailClient.send_report_to_user_with_attach")
            logger.error(e)
            raise Exception(e)
Esempio n. 20
0
    def _make_sendgrid_mail(self, message):
        mail = Mail()
        if message.sender:
            mail.from_email = Email(message.sender)
        else:
            mail.from_email = Email(self.default_sender)

        template_id = getattr(message, 'template_id', None)
        if template_id:
            mail.template_id = template_id

        if message.subject:
            mail.subject = message.subject

        if message.recipients:
            if type(message.recipients) == list:
                personalization = Personalization()
                for recipient in message.recipients:
                    personalization.add_to(Email(recipient))

                if message.cc:
                    if type(message.cc) == list:
                        for recipient in message.cc:
                            personalization.add_cc(Email(recipient))
                    else:
                        raise Exception("type(cc) must be list")

                if message.bcc:
                    if type(message.bcc) == list:
                        for recipient in message.bcc:
                            personalization.add_bcc(Email(recipient))
                    else:
                        raise Exception("type(bcc) must be list")

                dynamic_template_data = getattr(message,
                                                'dynamic_template_data', None)
                if dynamic_template_data:
                    personalization.dynamic_template_data = dynamic_template_data

                mail.add_personalization(personalization)
            else:
                raise Exception("unsupported type yet")
        if message.body:
            mail.add_content(Content("text/plain", message.body))

        if message.html:
            mail.add_content(Content("text/html", message.html))

        if message.reply_to:
            mail.reply_to = Email(message.reply_to)

        if message.attachments:
            for attachment in message.attachments:
                file_content = base64.b64encode(
                    attachment.data).decode('UTF-8')
                mail.add_attachment(
                    Attachment(
                        file_content=file_content,
                        file_name=attachment.filename,
                        file_type=attachment.content_type,
                        disposition=attachment.disposition,
                    ))

        return mail
Esempio n. 21
0
    def _build_sg_mail(self, email):
        mail = Mail()
        from_name, from_email = rfc822.parseaddr(email.from_email)
        # Python sendgrid client should improve
        # sendgrid/helpers/mail/mail.py:164
        if not from_name:
            from_name = None

        mail.from_email = Email(from_email, from_name)

        mail.subject = email.subject

        personalization = Personalization()
        for e in email.to:
            personalization.add_to(Email(e))
        for e in email.cc:
            personalization.add_cc(Email(e))
        for e in email.bcc:
            personalization.add_bcc(Email(e))
        personalization.subject = email.subject
        mail.add_content(Content("text/plain", email.body))
        if isinstance(email, EmailMultiAlternatives):
            for alt in email.alternatives:
                if alt[1] == "text/html":
                    mail.add_content(Content(alt[1], alt[0]))
        elif email.content_subtype == "html":
            mail.contents = []
            mail.add_content(Content("text/plain", ' '))
            mail.add_content(Content("text/html", email.body))

        if hasattr(email, 'categories'):
            for c in email.categories:
                mail.add_category(Category(c))

        if hasattr(email, 'template_id'):
            mail.template_id = email.template_id
            if hasattr(email, 'substitutions'):
                for k, v in email.substitutions.items():
                    personalization.add_substitution(Substitution(k, v))

        if hasattr(email, 'custom_args'):
            for item in email.custom_args:
                for k, v in item.items():
                    mail.add_custom_arg(CustomArg(k, v))

        for k, v in email.extra_headers.items():
            mail.add_header({k: v})

        for attachment in email.attachments:
            if isinstance(attachment, MIMEBase):
                attach = Attachment()
                attach.filename = attachment.get_filename()
                attach.content = base64.b64encode(attachment.get_payload())
                mail.add_attachment(attach)
            elif isinstance(attachment, tuple):
                attach = Attachment()
                attach.filename = attachment[0]
                base64_attachment = base64.b64encode(attachment[1])
                if sys.version_info >= (3,):
                    attach.content = str(base64_attachment, 'utf-8')
                else:
                    attach.content = base64_attachment
                attach.type = attachment[2]
                mail.add_attachment(attach)

        mail.add_personalization(personalization)
        return mail.get()
Esempio n. 22
0
def stuff():
    """
    Accept data from the form, generate, display, and email QR code to user
    """

    for user in db.session.query(User).all():
        if request.form['email'] == user.get_email():
            return 'Email address {} already found in database!\
            Please re-enter the form correctly!'.format(request.form['email'])

        if str(request.form['phone_number']) == str(user.get_phone()):
            return 'Phone number {} already found in database!\
            Please re-enter the form correctly!'.format(
                request.form['phone_number'])

    codex_id = get_current_id()

    user = User(name=request.form['name'],
                email=request.form['email'],
                phone=request.form['phone_number'],
                codex_id=codex_id,
                department=DEPARTMENTS[request.form['department']])
    try:
        db.session.add(user)
        db.session.commit()
    except exc.IntegrityError:
        return "Error occurred trying to enter values into the database!"

    img = generate_qr(request.form, codex_id)
    img.save('qr.png')
    img_data = open('qr.png', 'rb').read()
    encoded = base64.b64encode(img_data).decode()

    name = request.form['name']
    from_email = Email(FROM_EMAIL)
    to_email = Email(request.form['email'])
    p = None
    if request.form['email_second_person'] and request.form[
            'name_second_person']:
        cc_email = Email(request.form['email_second_person'])
        name += ', {}'.format(request.form['name_second_person'])
        p = Personalization()
        p.add_to(cc_email)

    subject = 'Registration for CodeX April 2019 - ID {}'.format(codex_id)
    message = """<img src='https://drive.google.com/uc?id=12VCUzNvU53f_mR7Hbumrc6N66rCQO5r-&export=download'>
    <hr>
    {}, your registration is done!
    <br/>
    A QR code has been attached below!
    <br/>
    You're <b>required</b> to present this on the day of the event.
    """.format(name)
    content = Content('text/html', message)
    mail = Mail(from_email, subject, to_email, content)
    if p:
        mail.add_personalization(p)

    attachment = Attachment()
    attachment.type = 'image/png'
    attachment.filename = 'qr.png'
    attachment.content = encoded

    mail.add_attachment(attachment)

    response = sg.client.mail.send.post(request_body=mail.get())
    print(response.status_code)
    print(response.body)
    print(response.headers)

    return 'Please save this QR Code. It has also been emailed to you.<br><img src=\
            "data:image/png;base64, {}"/>'.format(encoded)
Esempio n. 23
0
def send_summary_email(data, context):
    print(data, context)
    force_send = data.get('force_send', False)
    sg = sendgrid.SendGridAPIClient(api_key=os.environ['SENDGRID_API_KEY'])
    dt = datetime.datetime.now(pytz.timezone('US/Pacific'))

    client = datastore.Client()

    # cannot have multiple filters!?
    groups_query = client.query(
        kind='group',
        filters=[('end_date', '>=', (dt.date() - datetime.timedelta(days=1)).isoformat())],
    )
    subject_prefix = '[DEV] ' if IS_DEVELOPMENT else ''
    for group in groups_query.fetch():
        print(group)
        if dt.date().isoformat() < group['start_date']:
            continue

        final_summary_date = (
            datetime.datetime.strptime(group['end_date'], '%Y-%m-%d').date()
            + datetime.timedelta(days=1)
        ).isoformat()

        is_final = dt.date().isoformat() == final_summary_date
        if not force_send and dt.weekday() != 0 and not is_final and not IS_DEVELOPMENT:
            continue

        goals_query = client.query(
            kind='goal2',
            ancestor=group.key
        )

        goals = list(goals_query.fetch())
        if not goals:
            print('no goals found for group {}'.format(group))
            continue

        personalization = Personalization()
        total_progress = 0
        total_denominator = 0
        for goal in goals:
            print(goal)

            goal['denominator'] = len(goal.get('opportunities', []))
            goal['progress'] = len(goal.get('completions', []))
            goal['background-color'] = compute_goal_color(goal)
            goal['completed_last_week'] = False
            opportunities = goal.get('opportunities', [])
            if opportunities and max(opportunities) in goal.get('completions', []):
                goal['completed_last_week'] = True
            total_progress += goal['progress']
            total_denominator += goal['denominator']

            if IS_DEVELOPMENT and DEVELOPER_EMAIL_STRING not in goal['email']:
                continue
            personalization.add_to(To(email=goal['email']))

        goals = sorted(goals, key=lambda x: x['progress'] / goal['denominator'], reverse=True)
        template = TEMPLATE_ENV.get_template("summary_email.tmpl")
        rendered = template.render(**locals())

        mail = Mail(
            from_email=From(email="*****@*****.**"),
            subject=Subject(subject_prefix + "Eccountabot {}Summary {} {}".format(
                'Final ' if is_final else '', group['name'], dt.date().isoformat()
            )),
            html_content=Content("text/html", rendered)
        )
        mail.add_personalization(personalization)
        try:
            response = sg.client.mail.send.post(request_body=mail.get())
        except exceptions.BadRequestsError as e:
            print(e.body)
            raise
Esempio n. 24
0
    def _build_sg_mail(self, msg):
        mail = Mail()

        mail.from_email = Email(*self._parse_email_address(msg.from_email))
        mail.subject = msg.subject

        personalization = Personalization()
        for addr in msg.to:
            personalization.add_to(Email(*self._parse_email_address(addr)))

        for addr in msg.cc:
            personalization.add_cc(Email(*self._parse_email_address(addr)))

        for addr in msg.bcc:
            personalization.add_bcc(Email(*self._parse_email_address(addr)))

        personalization.subject = msg.subject

        for k, v in msg.extra_headers.items():
            if k.lower() == "reply-to":
                mail.reply_to = Email(v)
            else:
                personalization.add_header(Header(k, v))

        if hasattr(msg, "template_id"):
            mail.template_id = msg.template_id
            if hasattr(msg, "substitutions"):
                for k, v in msg.substitutions.items():
                    personalization.add_substitution(Substitution(k, v))

        # write through the ip_pool_name attribute
        if hasattr(msg, "ip_pool_name"):
            if not isinstance(msg.ip_pool_name, basestring):
                raise ValueError(
                    "ip_pool_name must be a string, got: {}; "
                    "see https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/"
                    "index.html#-Request-Body-Parameters".format(
                        type(msg.ip_pool_name)))
            if not 2 <= len(msg.ip_pool_name) <= 64:
                raise ValueError(
                    "the number of characters of ip_pool_name must be min 2 and max 64, got: {}; "
                    "see https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/"
                    "index.html#-Request-Body-Parameters".format(
                        len(msg.ip_pool_name)))
            mail.ip_pool_name = msg.ip_pool_name

        # write through the send_at attribute
        if hasattr(msg, "send_at"):
            if not isinstance(msg.send_at, int):
                raise ValueError(
                    "send_at must be an integer, got: {}; "
                    "see https://sendgrid.com/docs/API_Reference/SMTP_API/scheduling_parameters.html#-Send-At".format(
                        type(msg.send_at)))
            personalization.send_at = msg.send_at

        mail.add_personalization(personalization)

        if hasattr(msg, "reply_to") and msg.reply_to:
            if mail.reply_to:
                # If this code path is triggered, the reply_to on the sg mail was set in a header above
                reply_to = Email(*self._parse_email_address(msg.reply_to))
                if reply_to.email != mail.reply_to.email or reply_to.name != mail.reply_to.name:
                    raise ValueError("Sendgrid only allows 1 email in the reply-to field.  " +
                                     "Reply-To header value != reply_to property value.")

            if not isinstance(msg.reply_to, basestring):
                if len(msg.reply_to) > 1:
                    raise ValueError("Sendgrid only allows 1 email in the reply-to field")
                mail.reply_to = Email(*self._parse_email_address(msg.reply_to[0]))
            else:
                mail.reply_to = Email(*self._parse_email_address(msg.reply_to))

        for attch in msg.attachments:
            attachment = Attachment()

            if isinstance(attch, MIMEBase):
                filename = attch.get_filename()
                if not filename:
                    ext = mimetypes.guess_extension(attch.get_content_type())
                    filename = "part-{0}{1}".format(uuid.uuid4().hex, ext)
                attachment.filename = filename
                # todo: Read content if stream?
                attachment.content = attch.get_payload().replace("\n", "")
                attachment.type = attch.get_content_type()
                content_id = attch.get("Content-ID")
                if content_id:
                    # Strip brackets since sendgrid's api adds them
                    if content_id.startswith("<") and content_id.endswith(">"):
                        content_id = content_id[1:-1]
                    attachment.content_id = content_id
                    attachment.disposition = "inline"

            else:
                filename, content, mimetype = attch

                attachment.filename = filename
                # Convert content from chars to bytes, in both Python 2 and 3.
                # todo: Read content if stream?
                if isinstance(content, str):
                    content = content.encode('utf-8')
                attachment.content = base64.b64encode(content).decode()
                attachment.type = mimetype

            mail.add_attachment(attachment)

        msg.body = ' ' if msg.body == '' else msg.body

        if isinstance(msg, EmailMultiAlternatives):
            mail.add_content(Content("text/plain", msg.body))
            for alt in msg.alternatives:
                if alt[1] == "text/html":
                    mail.add_content(Content(alt[1], alt[0]))
        elif msg.content_subtype == "html":
            mail.add_content(Content("text/plain", " "))
            mail.add_content(Content("text/html", msg.body))
        else:
            mail.add_content(Content("text/plain", msg.body))

        if hasattr(msg, "categories"):
            for cat in msg.categories:
                mail.add_category(Category(cat))

        if hasattr(msg, "asm"):
            if "group_id" not in msg.asm:
                raise KeyError("group_id not found in asm")

            if "groups_to_display" in msg.asm:
                mail.asm = ASM(msg.asm["group_id"], msg.asm["groups_to_display"])
            else:
                mail.asm = ASM(msg.asm["group_id"])

        mail_settings = MailSettings()
        mail_settings.sandbox_mode = SandBoxMode(self.sandbox_mode)
        mail.mail_settings = mail_settings

        tracking_settings = TrackingSettings()
        tracking_settings.open_tracking = OpenTracking(self.track_email)
        mail.tracking_settings = tracking_settings

        return mail.get()
Esempio n. 25
0
def send_mail(from_email, _to_email, subject, body, html=False,
              from_name="Gitcoin.co", cc_emails=None, categories=None, debug_mode=False):
    """Send email via SendGrid."""
    # make sure this subscriber is saved
    if not settings.SENDGRID_API_KEY:
        logger.warning('No SendGrid API Key set. Not attempting to send email.')
        return

    if categories is None:
        categories = ['default']

    to_email = _to_email
    get_or_save_email_subscriber(to_email, 'internal')

    # setup
    from_name = str(from_name)
    subject = str(subject)
    sg = sendgrid.SendGridAPIClient(apikey=settings.SENDGRID_API_KEY)
    from_email = Email(from_email, from_name)
    to_email = Email(to_email)
    contenttype = "text/plain" if not html else "text/html"

    # build content
    content = Content(contenttype, html) if html else Content(contenttype, body)

    # TODO:  A bit of a hidden state change here.  Really confusing when doing development.
    #        Maybe this should be a variable passed into the function the value is set upstream? 
    if settings.IS_DEBUG_ENV or debug_mode:
        to_email = Email(settings.CONTACT_EMAIL)  # just to be double secret sure of what were doing in dev
        subject = _("[DEBUG] ") + subject

    mail = Mail(from_email, subject, to_email, content)
    response = None

    # build personalization
    if cc_emails:
        p = Personalization()
        p.add_to(to_email)
        for cc_addr in set(cc_emails):
            cc_addr = Email(cc_addr)
            if settings.IS_DEBUG_ENV:
                cc_addr = to_email
            if cc_addr._email != to_email._email:
                p.add_to(cc_addr)
        mail.add_personalization(p)

    # categories
    for category in categories:
        mail.add_category(Category(category))

    # debug logs
    logger.info(f"-- Sending Mail '{subject}' to {to_email}")
    try:
        response = sg.client.mail.send.post(request_body=mail.get())
    except UnauthorizedError as e:
        logger.error(f'-- Sendgrid Mail failure - Unauthorized - Check sendgrid credentials')
        logger.error(e)
    except HTTPError as e:
        logger.error(f'-- Sendgrid Mail failure - {e}')

    return response
Esempio n. 26
0
    def test_kitchenSink(self):
        self.maxDiff = None

        """All settings set"""
        mail = Mail()

        mail.from_email = Email("*****@*****.**", "Example User")

        mail.subject = "Hello World from the SendGrid Python Library"

        personalization = Personalization()
        personalization.add_to(Email("*****@*****.**", "Example User"))
        personalization.add_to(Email("*****@*****.**", "Example User"))
        personalization.add_cc(Email("*****@*****.**", "Example User"))
        personalization.add_cc(Email("*****@*****.**", "Example User"))
        personalization.add_bcc(Email("*****@*****.**"))
        personalization.add_bcc(Email("*****@*****.**"))
        personalization.subject = "Hello World from the Personalized SendGrid Python Library"
        personalization.add_header(Header("X-Test", "test"))
        personalization.add_header(Header("X-Mock", "true"))
        personalization.add_substitution(
            Substitution("%name%", "Example User"))
        personalization.add_substitution(Substitution("%city%", "Denver"))
        personalization.add_custom_arg(CustomArg("user_id", "343"))
        personalization.add_custom_arg(CustomArg("type", "marketing"))
        personalization.send_at = 1443636843
        mail.add_personalization(personalization)

        personalization2 = Personalization()
        personalization2.add_to(Email("*****@*****.**", "Example User"))
        personalization2.add_to(Email("*****@*****.**", "Example User"))
        personalization2.add_cc(Email("*****@*****.**", "Example User"))
        personalization2.add_cc(Email("*****@*****.**", "Example User"))
        personalization2.add_bcc(Email("*****@*****.**"))
        personalization2.add_bcc(Email("*****@*****.**"))
        personalization2.subject = "Hello World from the Personalized SendGrid Python Library"
        personalization2.add_header(Header("X-Test", "test"))
        personalization2.add_header(Header("X-Mock", "true"))
        personalization2.add_substitution(
            Substitution("%name%", "Example User"))
        personalization2.add_substitution(Substitution("%city%", "Denver"))
        personalization2.add_custom_arg(CustomArg("user_id", "343"))
        personalization2.add_custom_arg(CustomArg("type", "marketing"))
        personalization2.send_at = 1443636843
        mail.add_personalization(personalization2)

        mail.add_content(Content("text/plain", "some text here"))
        mail.add_content(
            Content(
                "text/html",
                "<html><body>some text here</body></html>"))

        attachment = Attachment()
        attachment.content = "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gQ3JhcyBwdW12"
        attachment.type = "application/pdf"
        attachment.filename = "balance_001.pdf"
        attachment.disposition = "attachment"
        attachment.content_id = "Balance Sheet"
        mail.add_attachment(attachment)

        attachment2 = Attachment()
        attachment2.content = "BwdW"
        attachment2.type = "image/png"
        attachment2.filename = "banner.png"
        attachment2.disposition = "inline"
        attachment2.content_id = "Banner"
        mail.add_attachment(attachment2)

        mail.template_id = "13b8f94f-bcae-4ec6-b752-70d6cb59f932"

        mail.add_section(
            Section(
                "%section1%",
                "Substitution Text for Section 1"))
        mail.add_section(
            Section(
                "%section2%",
                "Substitution Text for Section 2"))

        mail.add_header(Header("X-Test1", "test1"))
        mail.add_header(Header("X-Test3", "test2"))

        mail.add_header({"X-Test4": "test4"})

        mail.add_category(Category("May"))
        mail.add_category(Category("2016"))

        mail.add_custom_arg(CustomArg("campaign", "welcome"))
        mail.add_custom_arg(CustomArg("weekday", "morning"))

        mail.send_at = 1443636842

        mail.batch_id = "sendgrid_batch_id"

        mail.asm = ASM(99, [4, 5, 6, 7, 8])

        mail.ip_pool_name = "24"

        mail_settings = MailSettings()
        mail_settings.bcc_settings = BCCSettings(
            True, Email("*****@*****.**"))
        mail_settings.bypass_list_management = BypassListManagement(True)
        mail_settings.footer_settings = FooterSettings(
            True,
            "Footer Text",
            "<html><body>Footer Text</body></html>")
        mail_settings.sandbox_mode = SandBoxMode(True)
        mail_settings.spam_check = SpamCheck(
            True, 1, "https://spamcatcher.sendgrid.com")
        mail.mail_settings = mail_settings

        tracking_settings = TrackingSettings()
        tracking_settings.click_tracking = ClickTracking(
            True, True)
        tracking_settings.open_tracking = OpenTracking(
            True,
            "Optional tag to replace with the open image in the body of the message")
        tracking_settings.subscription_tracking = SubscriptionTracking(
            True,
            "text to insert into the text/plain portion of the message",
            "<html><body>html to insert into the text/html portion of the message</body></html>",
            "Optional tag to replace with the open image in the body of the message")
        tracking_settings.ganalytics = Ganalytics(
            True,
            "some source",
            "some medium",
            "some term",
            "some content",
            "some campaign")
        mail.tracking_settings = tracking_settings

        mail.reply_to = Email("*****@*****.**")

        expected_result = {
            "asm": {
                "group_id": 99,
                "groups_to_display": [4, 5, 6, 7, 8]
            },
            "attachments": [
                {
                    "content": "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3"
                               "RldHVyIGFkaXBpc2NpbmcgZWxpdC4gQ3JhcyBwdW12",
                    "content_id": "Balance Sheet",
                    "disposition": "attachment",
                    "filename": "balance_001.pdf",
                    "type": "application/pdf"
                },
                {
                    "content": "BwdW",
                    "content_id": "Banner",
                    "disposition": "inline",
                    "filename": "banner.png",
                    "type": "image/png"
                }
            ],
            "batch_id": "sendgrid_batch_id",
            "categories": [
                "May",
                "2016"
            ],
            "content": [
                {
                    "type": "text/plain",
                    "value": "some text here"
                },
                {
                    "type": "text/html",
                    "value": "<html><body>some text here</body></html>"
                }
            ],
            "custom_args": {
                "campaign": "welcome",
                "weekday": "morning"
            },
            "from": {
                "email": "*****@*****.**",
                "name": "Example User"
            },
            "headers": {
                "X-Test1": "test1",
                "X-Test3": "test2",
                "X-Test4": "test4"
            },
            "ip_pool_name": "24",
            "mail_settings": {
                "bcc": {
                    "email": "*****@*****.**",
                    "enable": True
                },
                "bypass_list_management": {
                    "enable": True
                },
                "footer": {
                    "enable": True,
                    "html": "<html><body>Footer Text</body></html>",
                    "text": "Footer Text"
                },
                "sandbox_mode": {
                    "enable": True
                },
                "spam_check": {
                    "enable": True,
                    "post_to_url": "https://spamcatcher.sendgrid.com",
                    "threshold": 1
                }
            },
            "personalizations": [
                {
                    "bcc": [
                        {
                            "email": "*****@*****.**"
                        },
                        {
                            "email": "*****@*****.**"
                        }
                    ],
                    "cc": [
                        {
                            "email": "*****@*****.**",
                            "name": "Example User"
                        },
                        {
                            "email": "*****@*****.**",
                            "name": "Example User"
                        }
                    ],
                    "custom_args": {
                        "type": "marketing",
                        "user_id": "343"
                    },
                    "headers": {
                        "X-Mock": "true",
                        "X-Test": "test"
                    },
                    "send_at": 1443636843,
                    "subject": "Hello World from the Personalized SendGrid "
                               "Python Library",
                    "substitutions": {
                        "%city%": "Denver",
                        "%name%": "Example User"
                    },
                    "to": [
                        {
                            "email": "*****@*****.**",
                            "name": "Example User"
                        },
                        {
                            "email": "*****@*****.**",
                            "name": "Example User"
                        }
                    ]
                },
                {
                    "bcc": [
                        {
                            "email": "*****@*****.**"
                        },
                        {
                            "email": "*****@*****.**"
                        }
                    ],
                    "cc": [
                        {
                            "email": "*****@*****.**",
                            "name": "Example User"
                        },
                        {
                            "email": "*****@*****.**",
                            "name": "Example User"
                        }
                    ],
                    "custom_args": {
                        "type": "marketing",
                        "user_id": "343"
                    },
                    "headers": {
                        "X-Mock": "true",
                        "X-Test": "test"
                    },
                    "send_at": 1443636843,
                    "subject": "Hello World from the Personalized SendGrid "
                               "Python Library",
                    "substitutions": {
                        "%city%": "Denver",
                        "%name%": "Example User"
                    },
                    "to": [
                        {
                            "email": "*****@*****.**",
                            "name": "Example User"
                        },
                        {
                            "email": "*****@*****.**",
                            "name": "Example User"
                        }
                    ]
                }
            ],
            "reply_to": {
                "email": "*****@*****.**"
            },
            "sections": {
                "%section1%": "Substitution Text for Section 1",
                "%section2%": "Substitution Text for Section 2"
            },
            "send_at": 1443636842,
            "subject": "Hello World from the SendGrid Python Library",
            "template_id": "13b8f94f-bcae-4ec6-b752-70d6cb59f932",
            "tracking_settings": {
                "click_tracking": {
                    "enable": True,
                    "enable_text": True
                },
                "ganalytics": {
                    "enable": True,
                    "utm_campaign": "some campaign",
                    "utm_content": "some content",
                    "utm_medium": "some medium",
                    "utm_source": "some source",
                    "utm_term": "some term"
                },
                "open_tracking": {
                    "enable": True,
                    "substitution_tag": "Optional tag to replace with the "
                                        "open image in the body of the message"
                },
                "subscription_tracking": {
                    "enable": True,
                    "html": "<html><body>html to insert into the text/html "
                            "portion of the message</body></html>",
                    "substitution_tag": "Optional tag to replace with the open"
                                        " image in the body of the message",
                    "text": "text to insert into the text/plain portion of"
                            " the message"
                }
            }
        }
        self.assertEqual(
            json.dumps(mail.get(), sort_keys=True),
            json.dumps(expected_result, sort_keys=True)
        )
Esempio n. 27
0
def send_mail(from_email,
              _to_email,
              subject,
              body,
              html=False,
              from_name="Gitcoin.co",
              cc_emails=None,
              categories=None):
    """Send email via SendGrid."""
    # make sure this subscriber is saved
    if not settings.SENDGRID_API_KEY:
        print('No SendGrid API Key set. Not attempting to send email.')
        return

    if categories is None:
        categories = ['default']

    to_email = _to_email
    get_or_save_email_subscriber(to_email, 'internal')

    # setup
    from_name = str(from_name)
    subject = str(subject)
    sg = sendgrid.SendGridAPIClient(apikey=settings.SENDGRID_API_KEY)
    from_email = Email(from_email, from_name)
    to_email = Email(to_email)
    contenttype = "text/plain" if not html else "text/html"

    # build content
    content = Content(contenttype, html) if html else Content(
        contenttype, body)
    if settings.IS_DEBUG_ENV:
        to_email = Email(
            settings.CONTACT_EMAIL
        )  # just to be double secret sure of what were doing in dev
        subject = _("[DEBUG] ") + subject
    mail = Mail(from_email, subject, to_email, content)
    response = None

    # build personalization
    if cc_emails:
        p = Personalization()
        p.add_to(to_email)
        for cc_addr in set(cc_emails):
            cc_addr = Email(cc_addr)
            if settings.IS_DEBUG_ENV:
                cc_addr = to_email
            if cc_addr._email != to_email._email:
                p.add_to(cc_addr)
        mail.add_personalization(p)

    # categories
    for category in categories:
        mail.add_category(Category(category))

    # debug logs
    print(f"-- Sending Mail '{subject}' to {_to_email}")

    # send mails
    try:
        response = sg.client.mail.send.post(request_body=mail.get())
    except UnauthorizedError:
        print(
            f'-- Sendgrid Mail failure - Unauthorized - Check sendgrid credentials'
        )
    except HTTPError as e:
        print(f'-- Sendgrid Mail failure - {e}')

    return response
Esempio n. 28
0
def send_email(  # pylint: disable=too-many-locals
    to: AddressesType,
    subject: str,
    html_content: str,
    files: Optional[AddressesType] = None,
    cc: Optional[AddressesType] = None,
    bcc: Optional[AddressesType] = None,
    sandbox_mode: bool = False,
    conn_id: str = "sendgrid_default",
    **kwargs,
) -> None:
    """
    Send an email with html content using `Sendgrid <https://sendgrid.com/>`__.

    .. note::
        For more information, see :ref:`email-configuration-sendgrid`
    """
    if files is None:
        files = []

    mail = Mail()
    from_email = kwargs.get('from_email') or os.environ.get(
        'SENDGRID_MAIL_FROM')
    from_name = kwargs.get('from_name') or os.environ.get(
        'SENDGRID_MAIL_SENDER')
    mail.from_email = Email(from_email, from_name)
    mail.subject = subject
    mail.mail_settings = MailSettings()

    if sandbox_mode:
        mail.mail_settings.sandbox_mode = SandBoxMode(enable=True)

    # Add the recipient list of to emails.
    personalization = Personalization()
    to = get_email_address_list(to)
    for to_address in to:
        personalization.add_to(Email(to_address))
    if cc:
        cc = get_email_address_list(cc)
        for cc_address in cc:
            personalization.add_cc(Email(cc_address))
    if bcc:
        bcc = get_email_address_list(bcc)
        for bcc_address in bcc:
            personalization.add_bcc(Email(bcc_address))

    # Add custom_args to personalization if present
    pers_custom_args = kwargs.get('personalization_custom_args')
    if isinstance(pers_custom_args, dict):
        for key in pers_custom_args.keys():
            personalization.add_custom_arg(
                CustomArg(key, pers_custom_args[key]))

    mail.add_personalization(personalization)
    mail.add_content(Content('text/html', html_content))

    categories = kwargs.get('categories', [])
    for cat in categories:
        mail.add_category(Category(cat))

    # Add email attachment.
    for fname in files:
        basename = os.path.basename(fname)

        with open(fname, "rb") as file:
            content = base64.b64encode(file.read()).decode('utf-8')

        attachment = Attachment(
            file_content=content,
            file_type=mimetypes.guess_type(basename)[0],
            file_name=basename,
            disposition="attachment",
            content_id=f"<{basename}>",
        )

        mail.add_attachment(attachment)
    _post_sendgrid_mail(mail.get(), conn_id)
Esempio n. 29
0
import sendgrid
from sendgrid.helpers.mail import Category, Content, Email, Mail, Personalization

from email_func import get_file_content, get_configurations

if __name__ == "__main__":
    mail = Mail()
    mail.from_email = Email("*****@*****.**", "Rahul Shelke")
    mail.subject = "This is test email from sendgrid."

    personalization = Personalization()
    personalization.add_to(Email("*****@*****.**", "Rahul Shelke"))
    personalization.add_to(Email("*****@*****.**", "Rahul Shelke"))
    personalization.add_cc(Email("*****@*****.**", "Rahul Shelke"))
    personalization.add_bcc(Email("*****@*****.**", "Rahul Shelke"))
    mail.add_personalization(personalization)

    html = get_file_content(
        "{template}.html".format(template="email")).decode("utf8")
    text = get_file_content(
        "{template}.txt".format(template="email")).decode("utf8")
    mail.add_content(Content("text/plain", text))
    mail.add_content(Content("text/html", html))

    config = get_configurations()
    try:
        sendgrid_client = sendgrid.SendGridAPIClient(
            config['SENDGRID']['apikey'])
        response = sendgrid_client.send(mail)
        print(response.status_code)
        print(response.body)
Esempio n. 30
0
    def send(self, users=None):
        # FIXME Imported here due to circular dependency issues.
        from mist.api.notifications.models import UserNotificationPolicy

        if not users:
            users = self.ntf.owner.members
        elif not isinstance(users, list):
            users = [users]

        for user in users:
            # Prepare each user's information. Note that users may either be
            # instances of mist.api.users.models.User or e-mail addresses.
            if isinstance(user, User):
                to = user.email
                full_name = user.get_nice_name()
                first_name = user.first_name or full_name
                unsub_link = self.ntf.get_unsub_link(user.id)
                query_kwargs = {'owner': self.ntf.owner, 'user_id': user.id}
            else:
                to = user  # Just an e-mail.
                full_name = first_name = ""
                unsub_link = self.ntf.get_unsub_link(user_id=None, email=user)
                query_kwargs = {'owner': self.ntf.owner, 'email': user}

            # Check the user's notification policy.
            try:
                np = UserNotificationPolicy.objects.get(**query_kwargs)
                if np.has_blocked(self.ntf):
                    continue
            except UserNotificationPolicy.DoesNotExist:
                log.debug('No UserNotificationPolicy found for %s', user)

            if config.SENDGRID_EMAIL_NOTIFICATIONS_KEY:
                # Initialize SendGrid client.
                sg = SendGridAPIClient(
                    apikey=config.SENDGRID_EMAIL_NOTIFICATIONS_KEY)
                mail = Mail()
                mail.from_email = Email(self.ntf.sender_email,
                                        self.ntf.sender_title)

                # Personalize e-mail.
                personalization = Personalization()
                personalization.subject = self.ntf.subject
                personalization.add_to(Email(to, full_name))
                sub = Substitution("%name%", first_name)
                personalization.add_substitution(sub)
                if unsub_link:
                    sub = Substitution("%nsub%", unsub_link)
                    personalization.add_substitution(sub)
                mail.add_personalization(personalization)

                # Add content.
                mail.add_content(Content("text/plain", self.ntf.text_body))
                if self.ntf.html_body:
                    mail.add_content(Content("text/html", self.ntf.html_body))

                # Attempt to send.
                try:
                    sg.client.mail.send.post(request_body=mail.get())
                except urllib2.URLError as exc:
                    log.exception(repr(exc))
                except Exception as exc:
                    log.exception(repr(exc))
            else:
                body = self.ntf.text_body.replace("%nsub%", unsub_link)
                send_email(self.ntf.subject,
                           body, [to],
                           sender=self.ntf.sender_email)
def obtain_mail(personalization, template):
    mail = Mail()
    mail.set_template_id(template)
    mail.set_from(Email(settings.DEFAULT_FROM_EMAIL, 'TapVet Team'))
    mail.add_personalization(personalization)
    return mail.get()
Esempio n. 32
0
    def _build_sg_mail(self, email):
        mail = Mail()
        from_name, from_email = rfc822.parseaddr(email.from_email)
        # Python sendgrid client should improve
        # sendgrid/helpers/mail/mail.py:164
        if not from_name:
            from_name = None
        mail.set_from(Email(from_email, from_name))
        mail.set_subject(email.subject)

        personalization = Personalization()
        for e in email.to:
            personalization.add_to(Email(e))
        for e in email.cc:
            personalization.add_cc(Email(e))
        for e in email.bcc:
            personalization.add_bcc(Email(e))
        personalization.set_subject(email.subject)
        mail.add_content(Content("text/plain", email.body))
        if isinstance(email, EmailMultiAlternatives):
            for alt in email.alternatives:
                if alt[1] == "text/html":
                    mail.add_content(Content(alt[1], alt[0]))
        elif email.content_subtype == "html":
            mail.contents = []
            mail.add_content(Content("text/plain", ' '))
            mail.add_content(Content("text/html", email.body))

        if hasattr(email, 'categories'):
            for c in email.categories:
                mail.add_category(Category(c))

        if hasattr(email, 'template_id'):
            mail.set_template_id(email.template_id)
            if hasattr(email, 'substitutions'):
                for key, value in email.substitutions.items():
                    personalization.add_substitution(Substitution(key, value))

        # SendGrid does not support adding Reply-To as an extra
        # header, so it needs to be manually removed if it exists.
        reply_to_string = ""
        for key, value in email.extra_headers.items():
            if key.lower() == "reply-to":
                reply_to_string = value
            else:
                mail.add_header({key: value})
        # Note that if you set a "Reply-To" header *and* the reply_to
        # attribute, the header's value will be used.
        if not mail.reply_to and hasattr(email, "reply_to") and email.reply_to:
            # SendGrid only supports setting Reply-To to a single address.
            # See https://github.com/sendgrid/sendgrid-csharp/issues/339.
            reply_to_string = email.reply_to[0]
        # Determine whether reply_to contains a name and email address, or
        # just an email address.
        if reply_to_string:
            reply_to_name, reply_to_email = rfc822.parseaddr(reply_to_string)
            if reply_to_name and reply_to_email:
                mail.set_reply_to(Email(reply_to_email, reply_to_name))
            elif reply_to_email:
                mail.set_reply_to(Email(reply_to_email))

        for attachment in email.attachments:
            if isinstance(attachment, MIMEBase):
                attach = Attachment()
                attach.set_filename(attachment.get_filename())
                attach.set_content(base64.b64encode(attachment.get_payload()))
                mail.add_attachment(attach)
            elif isinstance(attachment, tuple):
                attach = Attachment()
                attach.set_filename(attachment[0])
                base64_attachment = base64.b64encode(attachment[1])
                if sys.version_info >= (3, ):
                    attach.set_content(str(base64_attachment, 'utf-8'))
                else:
                    attach.set_content(base64_attachment)
                attach.set_type(attachment[2])
                mail.add_attachment(attach)

        mail.add_personalization(personalization)
        return mail.get()
Esempio n. 33
0
    def _build_sg_mail(self, msg):
        mail = Mail()

        mail.from_email = Email(*self._parse_email_address(msg.from_email))
        mail.subject = msg.subject

        personalization = Personalization()
        for addr in msg.to:
            personalization.add_to(Email(*self._parse_email_address(addr)))

        for addr in msg.cc:
            personalization.add_cc(Email(*self._parse_email_address(addr)))

        for addr in msg.bcc:
            personalization.add_bcc(Email(*self._parse_email_address(addr)))

        personalization.subject = msg.subject

        for k, v in msg.extra_headers.items():
            if k.lower() == "reply-to":
                mail.reply_to = Email(v)
            else:
                personalization.add_header(Header(k, v))

        if hasattr(msg, "template_id"):
            mail.template_id = msg.template_id
            if hasattr(msg, "substitutions"):
                for k, v in msg.substitutions.items():
                    personalization.add_substitution(Substitution(k, v))

        # write through the ip_pool_name attribute
        if hasattr(msg, "ip_pool_name"):
            if not isinstance(msg.ip_pool_name, basestring):
                raise ValueError(
                    "ip_pool_name must be a string, got: {}; "
                    "see https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/index.html#-Request-Body-Parameters"
                    .format(type(msg.ip_pool_name)))
            if not 2 <= len(msg.ip_pool_name) <= 64:
                raise ValueError(
                    "the number of characters of ip_pool_name must be min 2 and max 64, got: {}; "
                    "see https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/index.html#-Request-Body-Parameters"
                    .format(len(msg.ip_pool_name)))
            mail.ip_pool_name = msg.ip_pool_name

        # write through the send_at attribute
        if hasattr(msg, "send_at"):
            if not isinstance(msg.send_at, int):
                raise ValueError(
                    "send_at must be an integer, got: {}; "
                    "see https://sendgrid.com/docs/API_Reference/SMTP_API/scheduling_parameters.html#-Send-At"
                    .format(type(msg.send_at)))
            personalization.send_at = msg.send_at

        mail.add_personalization(personalization)

        if hasattr(msg, "reply_to") and msg.reply_to:
            if mail.reply_to:
                # If this code path is triggered, the reply_to on the sg mail was set in a header above
                reply_to = Email(*self._parse_email_address(msg.reply_to))
                if reply_to.email != mail.reply_to.email or reply_to.name != mail.reply_to.name:
                    raise ValueError(
                        "Sendgrid only allows 1 email in the reply-to field.  "
                        + "Reply-To header value != reply_to property value.")

            if not isinstance(msg.reply_to, basestring):
                if len(msg.reply_to) > 1:
                    raise ValueError(
                        "Sendgrid only allows 1 email in the reply-to field")
                mail.reply_to = Email(
                    *self._parse_email_address(msg.reply_to[0]))
            else:
                mail.reply_to = Email(*self._parse_email_address(msg.reply_to))

        for attch in msg.attachments:
            attachment = Attachment()

            if isinstance(attch, MIMEBase):
                filename = attch.get_filename()
                if not filename:
                    ext = mimetypes.guess_extension(attch.get_content_type())
                    filename = "part-{0}{1}".format(uuid.uuid4().hex, ext)
                attachment.filename = filename
                # todo: Read content if stream?
                attachment.content = attch.get_payload().replace("\n", "")
                attachment.type = attch.get_content_type()
                content_id = attch.get("Content-ID")
                if content_id:
                    # Strip brackets since sendgrid's api adds them
                    if content_id.startswith("<") and content_id.endswith(">"):
                        content_id = content_id[1:-1]
                    attachment.content_id = content_id
                    attachment.disposition = "inline"

            else:
                filename, content, mimetype = attch

                attachment.filename = filename
                # todo: Read content if stream?
                if isinstance(content, str):
                    content = content.encode()
                attachment.content = base64.b64encode(content).decode()
                attachment.type = mimetype

            mail.add_attachment(attachment)

        msg.body = ' ' if msg.body == '' else msg.body

        if isinstance(msg, EmailMultiAlternatives):
            mail.add_content(Content("text/plain", msg.body))
            for alt in msg.alternatives:
                if alt[1] == "text/html":
                    mail.add_content(Content(alt[1], alt[0]))
        elif msg.content_subtype == "html":
            mail.add_content(Content("text/plain", " "))
            mail.add_content(Content("text/html", msg.body))
        else:
            mail.add_content(Content("text/plain", msg.body))

        if hasattr(msg, "categories"):
            for cat in msg.categories:
                mail.add_category(Category(cat))

        if hasattr(msg, "asm"):
            if "group_id" not in msg.asm:
                raise KeyError("group_id not found in asm")

            if "groups_to_display" in msg.asm:
                mail.asm = ASM(msg.asm["group_id"],
                               msg.asm["groups_to_display"])
            else:
                mail.asm = ASM(msg.asm["group_id"])

        mail_settings = MailSettings()
        mail_settings.sandbox_mode = SandBoxMode(self.sandbox_mode)
        mail.mail_settings = mail_settings

        tracking_settings = TrackingSettings()
        tracking_settings.open_tracking = OpenTracking(self.track_email)
        mail.tracking_settings = tracking_settings

        return mail.get()
Esempio n. 34
0
    def _build_sg_mail(self, msg: EmailMessage) -> Dict:
        """
        Serializes a Django EmailMessage into its JSON representation.

        Returns a Dict of mail data to be consumed by the sendgrid api.
        """
        mail = Mail()

        mail.from_email = Email(*self._parse_email_address(msg.from_email))

        personalization = Personalization()
        for addr in msg.to:
            personalization.add_to(Email(*self._parse_email_address(addr)))

        for addr in msg.cc:
            personalization.add_cc(Email(*self._parse_email_address(addr)))

        for addr in msg.bcc:
            personalization.add_bcc(Email(*self._parse_email_address(addr)))

        if hasattr(msg, "custom_args"):
            for k, v in msg.custom_args.items():
                personalization.add_custom_arg(CustomArg(k, v))

        if self._is_transaction_template(msg):
            if msg.subject:
                logger.warning(
                    "Message subject is ignored in transactional template, "
                    "please add it as template variable (e.g. {{ subject }}")
                # See https://github.com/sendgrid/sendgrid-nodejs/issues/843
        else:
            personalization.subject = msg.subject

        for k, v in msg.extra_headers.items():
            if k.lower() == "reply-to":
                mail.reply_to = Email(v)
            else:
                personalization.add_header(Header(k, v))

        if hasattr(msg, "ip_pool_name"):
            if not isinstance(msg.ip_pool_name, str):
                raise ValueError(
                    "ip_pool_name must be a str, got: {}; ".format(
                        type(msg.ip_pool_name)))

            # Validate ip_pool_name length before attempting to add
            if not 2 <= len(msg.ip_pool_name) <= 64:
                raise ValueError(
                    "the number of characters of ip_pool_name must be min 2 and max 64, got: {}; "
                    "see https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/"
                    "index.html#-Request-Body-Parameters".format(
                        len(msg.ip_pool_name)))

            if SENDGRID_5:
                ip_pool_name = msg.ip_pool_name
            else:
                ip_pool_name = IpPoolName(msg.ip_pool_name)
            mail.ip_pool_name = ip_pool_name

        # write through the send_at attribute
        if hasattr(msg, "send_at"):
            if not isinstance(msg.send_at, int):
                raise ValueError(
                    "send_at must be an integer, got: {}; "
                    "see https://sendgrid.com/docs/API_Reference/SMTP_API/scheduling_parameters.html#-Send-At"
                    .format(type(msg.send_at)))
            personalization.send_at = msg.send_at

        if hasattr(msg, "reply_to") and msg.reply_to:
            if mail.reply_to:
                # If this code path is triggered, the reply_to on the sg mail was set in a header above
                reply_to = Email(*self._parse_email_address(msg.reply_to[0]))
                if (reply_to.email != mail.reply_to.email
                        or reply_to.name != mail.reply_to.name):
                    raise ValueError(
                        "Sendgrid only allows 1 email in the reply-to field.  "
                        + "Reply-To header value != reply_to property value.")

            if not isinstance(msg.reply_to, str):
                if len(msg.reply_to) > 1:
                    raise ValueError(
                        "Sendgrid only allows 1 email in the reply-to field")
                mail.reply_to = Email(
                    *self._parse_email_address(msg.reply_to[0]))
            else:
                mail.reply_to = Email(*self._parse_email_address(msg.reply_to))

        for attch in msg.attachments:
            sg_attch = self._create_sg_attachment(attch)
            mail.add_attachment(sg_attch)

        if self._is_transaction_template(msg):
            if msg.body:
                logger.warning(
                    "Message body is ignored in transactional template")
        else:
            msg.body = " " if msg.body == "" else msg.body

        if hasattr(msg, "template_id"):
            # Template mails should not have subject and content attributes
            mail.template_id = msg.template_id
            if hasattr(msg, "substitutions"):
                for k, v in msg.substitutions.items():
                    personalization.add_substitution(Substitution(k, v))
            if hasattr(msg, "dynamic_template_data"):
                if SENDGRID_5:
                    logger.warning(
                        "dynamic_template_data not available in sendgrid version < 6"
                    )
                personalization.dynamic_template_data = msg.dynamic_template_data

        if not self._is_transaction_template(msg):
            # In sendgrid v6 we should not specify subject and content between request parameter
            # when we are sending a request for a transactional template
            mail.subject = msg.subject
            if isinstance(msg, EmailMultiAlternatives):
                mail.add_content(Content("text/plain", msg.body))
                for alt in msg.alternatives:
                    if alt[1] == "text/html":
                        mail.add_content(Content(alt[1], alt[0]))
            elif msg.content_subtype == "html":
                mail.add_content(Content("text/plain", " "))
                mail.add_content(Content("text/html", msg.body))
            else:
                mail.add_content(Content("text/plain", msg.body))

        mail.add_personalization(personalization)

        if hasattr(msg, "categories"):
            for cat in msg.categories:
                mail.add_category(Category(cat))

        if hasattr(msg, "asm"):
            if "group_id" not in msg.asm:
                raise KeyError("group_id not found in asm")

            if "groups_to_display" in msg.asm:
                mail.asm = ASM(msg.asm["group_id"],
                               msg.asm["groups_to_display"])
            else:
                mail.asm = ASM(msg.asm["group_id"])

        mail_settings = MailSettings()
        mail_settings.sandbox_mode = SandBoxMode(self.sandbox_mode)
        mail.mail_settings = mail_settings

        tracking_settings = TrackingSettings()
        tracking_settings.open_tracking = OpenTracking(self.track_email)
        tracking_settings.click_tracking = ClickTracking(
            self.track_clicks_html, self.track_clicks_plain)

        mail.tracking_settings = tracking_settings

        return mail.get()
Esempio n. 35
0
def custom_send_mail(subject=None,
                     html_message=None,
                     from_email=None,
                     recipient_list=None,
                     text_message=None,
                     email_instance=None):
    """
    The role of this function is to handle the sending of an email message based on the configuration of the project setting.py file.
    - If settings.USE_SENDGRID = True, the mail will be sent with the python sendgrid package using the sendgrid REST api
    - If settings.USE_SMTP_EMAIL = True, the email will be send with django's send_mail function.
    - If settings.USE_SMTP_EMAIL and settings.USE_SENDGRID are both false, no email will be sent.

    :param subject:
    :param html_message:
    :param from_email:
    :param recipient_list:
    :return:
    """
    if email_instance:
        subject = email_instance.get_subject()
        text_message = email_instance.get_text_message()
        html_message = email_instance.get_html_message()
        from_email = email_instance.get_from_email()
        recipient_list = email_instance.get_recipient_list()

    if settings.USE_SENDGRID:
        sg = SendGridAPIClient(settings.SENDGRID_API_KEY)
        from_email = Email(from_email)
        to_list = Personalization()
        for email in set(recipient_list):
            to_list.add_to(Email(email))
        mail = Mail(from_email=from_email,
                    to_emails=None,
                    subject=subject,
                    html_content=html_message,
                    plain_text_content=text_message)
        mail.add_personalization(to_list)
        try:
            sg.send(mail)
        except BadRequestsError:
            print("bad request. email not sent")

    elif settings.USE_AWS_SES:
        my_config = Config(region_name='ca-central-1',
                           signature_version='v4',
                           retries={
                               'max_attempts': 10,
                               'mode': 'standard'
                           })
        # from https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-using-sdk-python.html
        # The character encoding for the email.
        CHARSET = "UTF-8"
        # Create a new SES resource and specify a region.
        client = boto3.client(
            'ses',
            aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
            aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
            config=my_config)
        # Try to send the email.
        try:
            # Provide the contents of the email.
            response = client.send_email(
                Destination={'ToAddresses': recipient_list},
                Message={
                    'Body': {
                        'Html': {
                            'Charset': CHARSET,
                            'Data': nz(html_message, ''),
                        },
                        'Text': {
                            'Charset': CHARSET,
                            'Data': nz(text_message, ''),
                        },
                    },
                    'Subject': {
                        'Charset': CHARSET,
                        'Data': subject,
                    },
                },
                Source=from_email,
            )
        # Display an error if something goes wrong.
        except ClientError as e:
            print(e.response['Error']['Message'])
        else:
            print("Email sent! Message ID:"),
            print(response['MessageId'])

    elif settings.USE_SMTP_EMAIL:
        django_send_mail(subject=subject,
                         message=nz(text_message, ''),
                         html_message=html_message,
                         from_email=from_email,
                         recipient_list=recipient_list,
                         fail_silently=False)

    else:
        print('No email configuration present in application...')
        if email_instance:
            print(email_instance)
        else:
            print("FROM: {}\nTO: {}\nSUBJECT: {}\nMESSAGE:{}".format(
                from_email, recipient_list, subject, html_message))
Esempio n. 36
0
    def test_kitchenSink(self):
        self.maxDiff = None
        """All settings set"""
        mail = Mail()

        mail.from_email = Email("*****@*****.**", "Example User")

        mail.subject = "Hello World from the SendGrid Python Library"

        personalization = Personalization()
        personalization.add_to(Email("*****@*****.**", "Example User"))
        personalization.add_to(Email("*****@*****.**", "Example User"))
        personalization.add_cc(Email("*****@*****.**", "Example User"))
        personalization.add_cc(Email("*****@*****.**", "Example User"))
        personalization.add_bcc(Email("*****@*****.**"))
        personalization.add_bcc(Email("*****@*****.**"))
        personalization.subject = "Hello World from the Personalized SendGrid Python Library"
        personalization.add_header(Header("X-Test", "test"))
        personalization.add_header(Header("X-Mock", "true"))
        personalization.add_substitution(Substitution("%name%",
                                                      "Example User"))
        personalization.add_substitution(Substitution("%city%", "Denver"))
        personalization.add_custom_arg(CustomArg("user_id", "343"))
        personalization.add_custom_arg(CustomArg("type", "marketing"))
        personalization.send_at = 1443636843
        mail.add_personalization(personalization)

        personalization2 = Personalization()
        personalization2.add_to(Email("*****@*****.**", "Example User"))
        personalization2.add_to(Email("*****@*****.**", "Example User"))
        personalization2.add_cc(Email("*****@*****.**", "Example User"))
        personalization2.add_cc(Email("*****@*****.**", "Example User"))
        personalization2.add_bcc(Email("*****@*****.**"))
        personalization2.add_bcc(Email("*****@*****.**"))
        personalization2.subject = "Hello World from the Personalized SendGrid Python Library"
        personalization2.add_header(Header("X-Test", "test"))
        personalization2.add_header(Header("X-Mock", "true"))
        personalization2.add_substitution(
            Substitution("%name%", "Example User"))
        personalization2.add_substitution(Substitution("%city%", "Denver"))
        personalization2.add_custom_arg(CustomArg("user_id", "343"))
        personalization2.add_custom_arg(CustomArg("type", "marketing"))
        personalization2.send_at = 1443636843
        mail.add_personalization(personalization2)

        mail.add_content(Content("text/plain", "some text here"))
        mail.add_content(
            Content("text/html", "<html><body>some text here</body></html>"))

        attachment = Attachment()
        attachment.content = "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gQ3JhcyBwdW12"
        attachment.type = "application/pdf"
        attachment.filename = "balance_001.pdf"
        attachment.disposition = "attachment"
        attachment.content_id = "Balance Sheet"
        mail.add_attachment(attachment)

        attachment2 = Attachment()
        attachment2.content = "BwdW"
        attachment2.type = "image/png"
        attachment2.filename = "banner.png"
        attachment2.disposition = "inline"
        attachment2.content_id = "Banner"
        mail.add_attachment(attachment2)

        mail.template_id = "13b8f94f-bcae-4ec6-b752-70d6cb59f932"

        mail.add_section(
            Section("%section1%", "Substitution Text for Section 1"))
        mail.add_section(
            Section("%section2%", "Substitution Text for Section 2"))

        mail.add_header(Header("X-Test1", "test1"))
        mail.add_header(Header("X-Test3", "test2"))

        mail.add_header({"X-Test4": "test4"})

        mail.add_category(Category("May"))
        mail.add_category(Category("2016"))

        mail.add_custom_arg(CustomArg("campaign", "welcome"))
        mail.add_custom_arg(CustomArg("weekday", "morning"))

        mail.send_at = 1443636842

        mail.batch_id = "sendgrid_batch_id"

        mail.asm = ASM(99, [4, 5, 6, 7, 8])

        mail.ip_pool_name = "24"

        mail_settings = MailSettings()
        mail_settings.bcc_settings = BCCSettings(True,
                                                 Email("*****@*****.**"))
        mail_settings.bypass_list_management = BypassListManagement(True)
        mail_settings.footer_settings = FooterSettings(
            True, "Footer Text", "<html><body>Footer Text</body></html>")
        mail_settings.sandbox_mode = SandBoxMode(True)
        mail_settings.spam_check = SpamCheck(
            True, 1, "https://spamcatcher.sendgrid.com")
        mail.mail_settings = mail_settings

        tracking_settings = TrackingSettings()
        tracking_settings.click_tracking = ClickTracking(True, True)
        tracking_settings.open_tracking = OpenTracking(
            True,
            "Optional tag to replace with the open image in the body of the message"
        )
        tracking_settings.subscription_tracking = SubscriptionTracking(
            True, "text to insert into the text/plain portion of the message",
            "<html><body>html to insert into the text/html portion of the message</body></html>",
            "Optional tag to replace with the open image in the body of the message"
        )
        tracking_settings.ganalytics = Ganalytics(True, "some source",
                                                  "some medium", "some term",
                                                  "some content",
                                                  "some campaign")
        mail.tracking_settings = tracking_settings

        mail.reply_to = Email("*****@*****.**")

        expected_result = {
            "asm": {
                "group_id": 99,
                "groups_to_display": [4, 5, 6, 7, 8]
            },
            "attachments": [{
                "content":
                "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3"
                "RldHVyIGFkaXBpc2NpbmcgZWxpdC4gQ3JhcyBwdW12",
                "content_id":
                "Balance Sheet",
                "disposition":
                "attachment",
                "filename":
                "balance_001.pdf",
                "type":
                "application/pdf"
            }, {
                "content": "BwdW",
                "content_id": "Banner",
                "disposition": "inline",
                "filename": "banner.png",
                "type": "image/png"
            }],
            "batch_id":
            "sendgrid_batch_id",
            "categories": ["May", "2016"],
            "content": [{
                "type": "text/plain",
                "value": "some text here"
            }, {
                "type": "text/html",
                "value": "<html><body>some text here</body></html>"
            }],
            "custom_args": {
                "campaign": "welcome",
                "weekday": "morning"
            },
            "from": {
                "email": "*****@*****.**",
                "name": "Example User"
            },
            "headers": {
                "X-Test1": "test1",
                "X-Test3": "test2",
                "X-Test4": "test4"
            },
            "ip_pool_name":
            "24",
            "mail_settings": {
                "bcc": {
                    "email": "*****@*****.**",
                    "enable": True
                },
                "bypass_list_management": {
                    "enable": True
                },
                "footer": {
                    "enable": True,
                    "html": "<html><body>Footer Text</body></html>",
                    "text": "Footer Text"
                },
                "sandbox_mode": {
                    "enable": True
                },
                "spam_check": {
                    "enable": True,
                    "post_to_url": "https://spamcatcher.sendgrid.com",
                    "threshold": 1
                }
            },
            "personalizations": [{
                "bcc": [{
                    "email": "*****@*****.**"
                }, {
                    "email": "*****@*****.**"
                }],
                "cc": [{
                    "email": "*****@*****.**",
                    "name": "Example User"
                }, {
                    "email": "*****@*****.**",
                    "name": "Example User"
                }],
                "custom_args": {
                    "type": "marketing",
                    "user_id": "343"
                },
                "headers": {
                    "X-Mock": "true",
                    "X-Test": "test"
                },
                "send_at":
                1443636843,
                "subject":
                "Hello World from the Personalized SendGrid "
                "Python Library",
                "substitutions": {
                    "%city%": "Denver",
                    "%name%": "Example User"
                },
                "to": [{
                    "email": "*****@*****.**",
                    "name": "Example User"
                }, {
                    "email": "*****@*****.**",
                    "name": "Example User"
                }]
            }, {
                "bcc": [{
                    "email": "*****@*****.**"
                }, {
                    "email": "*****@*****.**"
                }],
                "cc": [{
                    "email": "*****@*****.**",
                    "name": "Example User"
                }, {
                    "email": "*****@*****.**",
                    "name": "Example User"
                }],
                "custom_args": {
                    "type": "marketing",
                    "user_id": "343"
                },
                "headers": {
                    "X-Mock": "true",
                    "X-Test": "test"
                },
                "send_at":
                1443636843,
                "subject":
                "Hello World from the Personalized SendGrid "
                "Python Library",
                "substitutions": {
                    "%city%": "Denver",
                    "%name%": "Example User"
                },
                "to": [{
                    "email": "*****@*****.**",
                    "name": "Example User"
                }, {
                    "email": "*****@*****.**",
                    "name": "Example User"
                }]
            }],
            "reply_to": {
                "email": "*****@*****.**"
            },
            "sections": {
                "%section1%": "Substitution Text for Section 1",
                "%section2%": "Substitution Text for Section 2"
            },
            "send_at":
            1443636842,
            "subject":
            "Hello World from the SendGrid Python Library",
            "template_id":
            "13b8f94f-bcae-4ec6-b752-70d6cb59f932",
            "tracking_settings": {
                "click_tracking": {
                    "enable": True,
                    "enable_text": True
                },
                "ganalytics": {
                    "enable": True,
                    "utm_campaign": "some campaign",
                    "utm_content": "some content",
                    "utm_medium": "some medium",
                    "utm_source": "some source",
                    "utm_term": "some term"
                },
                "open_tracking": {
                    "enable":
                    True,
                    "substitution_tag":
                    "Optional tag to replace with the "
                    "open image in the body of the message"
                },
                "subscription_tracking": {
                    "enable":
                    True,
                    "html":
                    "<html><body>html to insert into the text/html "
                    "portion of the message</body></html>",
                    "substitution_tag":
                    "Optional tag to replace with the open"
                    " image in the body of the message",
                    "text":
                    "text to insert into the text/plain portion of"
                    " the message"
                }
            }
        }
        self.assertEqual(json.dumps(mail.get(), sort_keys=True),
                         json.dumps(expected_result, sort_keys=True))
Esempio n. 37
0
    def _build_sg_mail(self, msg):
        mail = Mail()

        mail.from_email = Email(*self._parse_email_address(msg.from_email))
        mail.subject = msg.subject

        personalization = Personalization()
        for addr in msg.to:
            personalization.add_to(Email(*self._parse_email_address(addr)))

        for addr in msg.cc:
            personalization.add_cc(Email(*self._parse_email_address(addr)))

        for addr in msg.bcc:
            personalization.add_bcc(Email(*self._parse_email_address(addr)))

        if hasattr(msg, 'custom_args'):
            for k, v in msg.custom_args.items():
                personalization.add_custom_arg(CustomArg(k, v))

        personalization.subject = msg.subject

        for k, v in msg.extra_headers.items():
            if k.lower() == "reply-to":
                mail.reply_to = Email(v)
            else:
                personalization.add_header(Header(k, v))

        if hasattr(msg, "template_id"):
            mail.template_id = msg.template_id
            if hasattr(msg, "substitutions"):
                for k, v in msg.substitutions.items():
                    personalization.add_substitution(Substitution(k, v))
            if hasattr(msg, "dynamic_template_data"):
                personalization.dynamic_template_data = msg.dynamic_template_data

        if hasattr(msg, "ip_pool_name"):
            if not isinstance(msg.ip_pool_name, basestring):
                raise ValueError(
                    "ip_pool_name must be a {}, got: {}; ".format(
                        type(msg.ip_pool_name)))

            # Validate ip_pool_name length before attempting to add
            if not 2 <= len(msg.ip_pool_name) <= 64:
                raise ValueError(
                    "the number of characters of ip_pool_name must be min 2 and max 64, got: {}; "
                    "see https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/"
                    "index.html#-Request-Body-Parameters".format(
                        len(msg.ip_pool_name)))

            if SENDGRID_VERSION < "6":
                ip_pool_name = msg.ip_pool_name
            else:
                ip_pool_name = IpPoolName(msg.ip_pool_name)
            mail.ip_pool_name = ip_pool_name

        # write through the send_at attribute
        if hasattr(msg, "send_at"):
            if not isinstance(msg.send_at, int):
                raise ValueError(
                    "send_at must be an integer, got: {}; "
                    "see https://sendgrid.com/docs/API_Reference/SMTP_API/scheduling_parameters.html#-Send-At".format(
                        type(msg.send_at)))
            personalization.send_at = msg.send_at

        mail.add_personalization(personalization)

        if hasattr(msg, "reply_to") and msg.reply_to:
            if mail.reply_to:
                # If this code path is triggered, the reply_to on the sg mail was set in a header above
                reply_to = Email(*self._parse_email_address(msg.reply_to))
                if reply_to.email != mail.reply_to.email or reply_to.name != mail.reply_to.name:
                    raise ValueError("Sendgrid only allows 1 email in the reply-to field.  " +
                                     "Reply-To header value != reply_to property value.")

            if not isinstance(msg.reply_to, basestring):
                if len(msg.reply_to) > 1:
                    raise ValueError("Sendgrid only allows 1 email in the reply-to field")
                mail.reply_to = Email(*self._parse_email_address(msg.reply_to[0]))
            else:
                mail.reply_to = Email(*self._parse_email_address(msg.reply_to))

        for attch in msg.attachments:
            sg_attch = self._create_sg_attachment(attch)
            mail.add_attachment(sg_attch)

        msg.body = ' ' if msg.body == '' else msg.body

        if isinstance(msg, EmailMultiAlternatives):
            mail.add_content(Content("text/plain", msg.body))
            for alt in msg.alternatives:
                if alt[1] == "text/html":
                    mail.add_content(Content(alt[1], alt[0]))
        elif msg.content_subtype == "html":
            mail.add_content(Content("text/plain", " "))
            mail.add_content(Content("text/html", msg.body))
        else:
            mail.add_content(Content("text/plain", msg.body))

        if hasattr(msg, "categories"):
            for cat in msg.categories:
                mail.add_category(Category(cat))

        if hasattr(msg, "asm"):
            if "group_id" not in msg.asm:
                raise KeyError("group_id not found in asm")

            if "groups_to_display" in msg.asm:
                mail.asm = ASM(msg.asm["group_id"], msg.asm["groups_to_display"])
            else:
                mail.asm = ASM(msg.asm["group_id"])

        mail_settings = MailSettings()
        mail_settings.sandbox_mode = SandBoxMode(self.sandbox_mode)
        mail.mail_settings = mail_settings

        tracking_settings = TrackingSettings()
        tracking_settings.open_tracking = OpenTracking(self.track_email)
        tracking_settings.click_tracking = ClickTracking(self.track_click)
        tracking_settings.subscription_tracking = SubscriptionTracking(self.subscription)
        mail.tracking_settings = tracking_settings

        return mail.get()
Esempio n. 38
0
    def _prepare_sendgrid_data(self):
        """
        Prepare and creates the Sendgrid Email object
        :return: sendgrid.helpers.mail.Email object
        """
        self.ensure_one()
        s_mail = Mail()
        s_mail.from_email = Email(self.email_from)
        if self.reply_to:
            s_mail.reply_to = Email(self.reply_to)

        # Add custom fields to match the tracking
        s_mail.add_custom_arg(CustomArg('odoo_id', self.message_id))
        s_mail.add_custom_arg(CustomArg('odoo_db', self.env.cr.dbname))

        headers = {'Message-Id': self.message_id}
        if self.headers:
            try:
                headers.update(safe_eval(self.headers))
            except Exception:
                pass
        for h_name, h_val in headers.iteritems():
            s_mail.add_header(Header(h_name, h_val))

        html = self.body_html or ' '

        p = re.compile(r'<.*?>')  # Remove HTML markers
        text_only = self.body_text or p.sub('', html.replace('<br/>', '\n'))

        s_mail.add_content(Content("text/plain", text_only or ' '))
        s_mail.add_content(Content("text/html", html))

        test_address = config.get('sendgrid_test_address')

        # We use only one personalization for transactional e-mail
        personalization = Personalization()
        subject = self.subject and self.subject.encode(
            "utf_8") or "(No subject)"
        personalization.subject = subject
        addresses = set()
        if not test_address:
            if self.email_to:
                addresses = set(self.email_to.split(','))
                for address in addresses:
                    personalization.add_to(Email(address))
            for recipient in self.recipient_ids:
                if recipient.email not in addresses:
                    personalization.add_to(Email(recipient.email))
                    addresses.add(recipient.email)
            if self.email_cc and self.email_cc not in addresses:
                personalization.add_cc(Email(self.email_cc))
        else:
            _logger.info(
                'Sending email to test address {}'.format(test_address))
            personalization.add_to(Email(test_address))
            self.email_to = test_address

        if self.sendgrid_template_id:
            s_mail.template_id = self.sendgrid_template_id.remote_id

        for substitution in self.substitution_ids:
            personalization.add_substitution(
                Substitution(substitution.key,
                             substitution.value.encode('utf-8')))

        s_mail.add_personalization(personalization)

        for attachment in self.attachment_ids:
            s_attachment = Attachment()
            # Datas are not encoded properly for sendgrid
            s_attachment.content = base64.b64encode(
                base64.b64decode(attachment.datas))
            s_attachment.filename = attachment.name
            s_mail.add_attachment(s_attachment)

        return s_mail
Esempio n. 39
0
def sender_alert_new_cmd(order, user):
    """
    Send the email to the owner for the new order.
    """

    date_cmd = str(order.created).split(' ')[0].split('-')
    data = {
        "cmd": {
            "ref": order.reference,
            "nameclient": f"{user.last_name.upper()} {user.first_name}",
            "email": user.email,
            "adress": user.adress,
            "postalcode": str(user.postal_code),
            "city": user.city.upper(),
            "phonenumber": f"0{str(user.phone_number)}",
            "anotheradress": {},
            "note": order.note,
            "date": f"{date_cmd[2]}/{date_cmd[1]}/{date_cmd[0]}",
            "subtotalprice": str(order.total_price - order.shipping_costs),
            "totalprice": str(order.total_price),
            "shippingcosts": str(order.shipping_costs),
            "products": []
        }
    }

    if order.another_delivery_adress:
        data['cmd']['anotheradress'] = {
            "ifyes": True,
            "nameclient": f"{order.last_name.upper()} {order.first_name}",
            "adress": order.adress,
            "postalcode": str(order.postal_code),
            "city": order.city.upper(),
            "phonenumber": f"0{str(order.phone_number)}",
        }

    else:
        data['cmd']['anotheradress'] = {
            "ifyes": False,
            "nameclient": "none",
            "adress": "none",
            "postalcode": "none",
            "city": "none",
            "phonenumber": "none",
        }

    for product in OrderProductQuantity.objects.filter(id_order=order):
        data['cmd']['products'].append({
            "name": product.id_product.name,
            "priceunit": str(product.price),
            "totalprice": str(product.get_price()),
            "quantity": str(product.quantity)
        })

    mail = Mail()
    mail.from_email = Email(
        os.environ.get('FROM_EMAIL'),
        os.environ.get('FROM_NAME_EMAIL')
    )
    mail.template_id = os.environ.get('ID_TEMPLATE_NEW_CMD')
    mail.subject = "NOUVELLE COMMANDE WEB"
    p = Personalization()
    p.add_to(Email(
        os.environ.get('OWNER_EMAIL'),
        os.environ.get('OWNER_NAME_EMAIL')
    ))
    p.dynamic_template_data = data
    mail.add_personalization(p)
    sg = SendGridAPIClient(api_key=os.environ.get('SENDGRID_API_KEY'))
    response = sg.client.mail.send.post(request_body=mail.get())

    return response