Пример #1
0
def send_email(user: User, subject: str, from_email: str, substitutions: [Dict[Any, Any]], content: str='text') -> Dict[
    str, str]:
    """
    This function sends an email using the SendGrid API
    Args:
       from_email: the email from which the email is sent
       user: the USer object containing the name and email address of the intended recipient
       subject: subject of email
       content: content

    Returns:
       Dict[str, str]: Dictionary containing HTTP response

    """
    content = Content("text/html", content)
    sendgrid_api = os.getenv("SENDGRID_API")
    sg = sendgrid.SendGridAPIClient(apikey=sendgrid_api)
    from_email = Email(from_email, name="Service Admin")
    to_email = Email(user.email, user.first_name)
    m = Mail(from_email, subject, to_email, content)
    for key, value in substitutions.items():
        m.personalizations[0].add_substitution(Substitution(key, value))
    if os.environ.get('ENV') == 'test':
        settings = MailSettings()
        settings.sandbox_mode = SandBoxMode(enable=True)
        m.mail_settings = settings
    m.template_id = '5a1b969f-77c5-4d27-8b6e-e77c9c237a8e'
    try:
        response = sg.client.mail.send.post(request_body=m.get())
    except exceptions.BadRequestsError as e:
        exit()
    return response
Пример #2
0
        def send_email(email: Mail) -> int:
            if self._sandbox:
                self.log_warning('Sandbox mode, not delivering email %s',
                                 email)
                email.mail_settings = MailSettings()
                email.mail_settings.sandbox_mode = SandBoxMode()
                email.mail_settings.sandbox_mode.enable = True

            response = client.send(email.get())
            return response.status_code
Пример #3
0
def send_email(subject, content):
    sendgrid_client = SendGridAPIClient(
        api_key=os.environ.get('SENDGRID_API_KEY'))
    message = Mail(
        from_email='*****@*****.**',
        to_emails='*****@*****.**',
        subject=subject,
        plain_text_content=content,
    )
    sand_box = os.environ.get('SAND_BOX')

    if sand_box == 'true':
        mail_settings = MailSettings()
        mail_settings.sandbox_mode = SandBoxMode(True)
        message.mail_settings = mail_settings

    return sendgrid_client.send(message)
Пример #4
0
def send_async_email(email_info):
    """Send an email."""
    app.logger.info("Sending email")
    from_email = Email(email=os.environ.get("EMAIL_ADDR"), name=os.environ.get("EMAIL_NAME", ""))
    message = Mail(from_email=from_email, to_emails=email_info['to_email'], subject=email_info['subject'],
                   html_content=email_info['content'])

    if app.config.get('TESTING'):
        sbm = SandBoxMode(True)
        message.mail_settings = MailSettings(sandbox_mode=sbm)
    try:
        sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
        response = sg.send(message)
        if app.config.get('TESTING') and response.status_code != 200:
            raise Exception("Could not send email:\n{}".format(message.get()))
        elif not app.config.get('TESTING') and response.status_code != 202:
            app.logger.error("Could not send email:\n{}".format(message.get()))
    except Exception as e:
        app.logger.error("Error sending email: \n{}".format(e))
Пример #5
0
    def render_output(self, content, blobs):
        msg = Mail(
            from_email=self.email_from,
            to_emails=self.email_to,
            subject=self.report.title,
            html_content=transform(content.get_format("html")),
        )

        if self._sandbox_mode:
            LOG.warn(
                ("Sandbox mode is enabled. Mails can only be verified, not "
                 "delivered."))
            msg.mail_settings = MailSettings()
            msg.mail_settings.sandbox_mode = SandBoxMode(True)

        attachment = []
        for blob in blobs:
            encoded_content = b64encode(blob.content.getvalue()).decode()
            attachment.append(
                Attachment(
                    file_content=encoded_content,
                    file_name=blob.id,
                    file_type=blob.mime_type,
                    content_id=blob.id,
                    disposition="inline",
                ))
        msg.attachment = attachment

        try:
            sg = SendGridAPIClient(self.api_key)
            res = sg.send(msg)

            LOG.debug(res.body)
            LOG.debug(res.headers)

            if res.status_code != 202:
                raise ValueError(
                    f"Unexpected HTTP response: {res.status_code}")
        except Exception as e:
            raise ValueError("Error sending mail",
                             self._parse_sendgrid_error(e))
Пример #6
0
def send_mail(
    subject: str,
    message_text: str,
    to_emails: List[str],
    send_from_email: str,
    sendgrid_api_key: str,
    sandbox_mode: bool = False,
) -> bool:
    """
    Send an email via Sendgrid. Configure API_KEY via constants.

    Arguments:
        subject {str} -- Subject line of email.
        message_text {str} -- Text of email.
        to_emails {List[str]} -- Destination email. The first element in the list will be
        considered the primary recipient.
        sandbox_mode {bool} -- If True, only do a dry run without actually sending the email.

    Returns:
        bool -- True if succesful.
    """
    sg_client = sendgrid.SendGridAPIClient(sendgrid_api_key)
    from_email = From(send_from_email)
    to_email = To(to_emails)
    content = Content("text/plain", message_text)
    mail = Mail(from_email, to_email, subject, content)

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

    response = sg_client.send(mail)

    # If this is a dry run, we get back 200 (OK) if the inputs are valid
    validated = sandbox_mode and response.status_code == 200

    # If this is a real run, we get back 202 (Accepted) if the message sent
    sent_succesfully = not sandbox_mode and response.status_code == 202

    return validated or sent_succesfully
Пример #7
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)
Пример #8
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())
    def test_kitchen_sink(self):
        from sendgrid.helpers.mail import (
            Mail, From, To, Cc, Bcc, Subject, Substitution, Header, CustomArg,
            SendAt, Content, MimeType, Attachment, FileName, FileContent,
            FileType, Disposition, ContentId, TemplateId, Section, ReplyTo,
            Category, BatchId, Asm, GroupId, GroupsToDisplay, IpPoolName,
            MailSettings, BccSettings, BccSettingsEmail, BypassListManagement,
            FooterSettings, FooterText, FooterHtml, SandBoxMode, SpamCheck,
            SpamThreshold, SpamUrl, TrackingSettings, ClickTracking,
            SubscriptionTracking, SubscriptionText, SubscriptionHtml,
            SubscriptionSubstitutionTag, OpenTracking,
            OpenTrackingSubstitutionTag, Ganalytics, UtmSource, UtmMedium,
            UtmTerm, UtmContent, UtmCampaign)

        self.maxDiff = None

        message = Mail()

        # Define Personalizations

        message.to = To('*****@*****.**', 'Example User1', p=0)
        message.to = [
            To('*****@*****.**', 'Example User2', p=0),
            To('*****@*****.**', 'Example User3', p=0)
        ]

        message.cc = Cc('*****@*****.**', 'Example User4', p=0)
        message.cc = [
            Cc('*****@*****.**', 'Example User5', p=0),
            Cc('*****@*****.**', 'Example User6', p=0)
        ]

        message.bcc = Bcc('*****@*****.**', 'Example User7', p=0)
        message.bcc = [
            Bcc('*****@*****.**', 'Example User8', p=0),
            Bcc('*****@*****.**', 'Example User9', p=0)
        ]

        message.subject = Subject('Sending with SendGrid is Fun 0', p=0)

        message.header = Header('X-Test1', 'Test1', p=0)
        message.header = Header('X-Test2', 'Test2', p=0)
        message.header = [
            Header('X-Test3', 'Test3', p=0),
            Header('X-Test4', 'Test4', p=0)
        ]

        message.substitution = Substitution('%name1%', 'Example Name 1', p=0)
        message.substitution = Substitution('%city1%', 'Example City 1', p=0)
        message.substitution = [
            Substitution('%name2%', 'Example Name 2', p=0),
            Substitution('%city2%', 'Example City 2', p=0)
        ]

        message.custom_arg = CustomArg('marketing1', 'true', p=0)
        message.custom_arg = CustomArg('transactional1', 'false', p=0)
        message.custom_arg = [
            CustomArg('marketing2', 'false', p=0),
            CustomArg('transactional2', 'true', p=0)
        ]

        message.send_at = SendAt(1461775051, p=0)

        message.to = To('*****@*****.**', 'Example User10', p=1)
        message.to = [
            To('*****@*****.**', 'Example User11', p=1),
            To('*****@*****.**', 'Example User12', p=1)
        ]

        message.cc = Cc('*****@*****.**', 'Example User13', p=1)
        message.cc = [
            Cc('*****@*****.**', 'Example User14', p=1),
            Cc('*****@*****.**', 'Example User15', p=1)
        ]

        message.bcc = Bcc('*****@*****.**', 'Example User16', p=1)
        message.bcc = [
            Bcc('*****@*****.**', 'Example User17', p=1),
            Bcc('*****@*****.**', 'Example User18', p=1)
        ]

        message.header = Header('X-Test5', 'Test5', p=1)
        message.header = Header('X-Test6', 'Test6', p=1)
        message.header = [
            Header('X-Test7', 'Test7', p=1),
            Header('X-Test8', 'Test8', p=1)
        ]

        message.substitution = Substitution('%name3%', 'Example Name 3', p=1)
        message.substitution = Substitution('%city3%', 'Example City 3', p=1)
        message.substitution = [
            Substitution('%name4%', 'Example Name 4', p=1),
            Substitution('%city4%', 'Example City 4', p=1)
        ]

        message.custom_arg = CustomArg('marketing3', 'true', p=1)
        message.custom_arg = CustomArg('transactional3', 'false', p=1)
        message.custom_arg = [
            CustomArg('marketing4', 'false', p=1),
            CustomArg('transactional4', 'true', p=1)
        ]

        message.send_at = SendAt(1461775052, p=1)

        message.subject = Subject('Sending with SendGrid is Fun 1', p=1)

        # The values below this comment are global to entire message

        message.from_email = From('*****@*****.**', 'Twilio SendGrid')

        message.reply_to = ReplyTo('*****@*****.**',
                                   'Twilio SendGrid Reply')

        message.subject = Subject('Sending with SendGrid is Fun 2')

        message.content = Content(MimeType.text,
                                  'and easy to do anywhere, even with Python')
        message.content = Content(
            MimeType.html,
            '<strong>and easy to do anywhere, even with Python</strong>')
        message.content = [
            Content('text/calendar', 'Party Time!!'),
            Content('text/custom', 'Party Time 2!!')
        ]

        message.attachment = Attachment(
            FileContent('base64 encoded content 1'),
            FileName('balance_001.pdf'), FileType('application/pdf'),
            Disposition('attachment'), ContentId('Content ID 1'))
        message.attachment = [
            Attachment(FileContent('base64 encoded content 2'),
                       FileName('banner.png'), FileType('image/png'),
                       Disposition('inline'), ContentId('Content ID 2')),
            Attachment(FileContent('base64 encoded content 3'),
                       FileName('banner2.png'), FileType('image/png'),
                       Disposition('inline'), ContentId('Content ID 3'))
        ]

        message.template_id = TemplateId(
            '13b8f94f-bcae-4ec6-b752-70d6cb59f932')

        message.section = Section('%section1%',
                                  'Substitution for Section 1 Tag')
        message.section = [
            Section('%section2%', 'Substitution for Section 2 Tag'),
            Section('%section3%', 'Substitution for Section 3 Tag')
        ]

        message.header = Header('X-Test9', 'Test9')
        message.header = Header('X-Test10', 'Test10')
        message.header = [
            Header('X-Test11', 'Test11'),
            Header('X-Test12', 'Test12')
        ]

        message.category = Category('Category 1')
        message.category = Category('Category 2')
        message.category = [Category('Category 1'), Category('Category 2')]

        message.custom_arg = CustomArg('marketing5', 'false')
        message.custom_arg = CustomArg('transactional5', 'true')
        message.custom_arg = [
            CustomArg('marketing6', 'true'),
            CustomArg('transactional6', 'false')
        ]

        message.send_at = SendAt(1461775053)

        message.batch_id = BatchId("HkJ5yLYULb7Rj8GKSx7u025ouWVlMgAi")

        message.asm = Asm(GroupId(1), GroupsToDisplay([1, 2, 3, 4]))

        message.ip_pool_name = IpPoolName("IP Pool Name")

        mail_settings = MailSettings()
        mail_settings.bcc_settings = BccSettings(
            False, BccSettingsEmail("*****@*****.**"))
        mail_settings.bypass_list_management = BypassListManagement(False)
        mail_settings.footer_settings = FooterSettings(
            True, FooterText("w00t"), FooterHtml("<string>w00t!<strong>"))
        mail_settings.sandbox_mode = SandBoxMode(True)
        mail_settings.spam_check = SpamCheck(True, SpamThreshold(5),
                                             SpamUrl("https://example.com"))
        message.mail_settings = mail_settings

        tracking_settings = TrackingSettings()
        tracking_settings.click_tracking = ClickTracking(True, False)
        tracking_settings.open_tracking = OpenTracking(
            True, OpenTrackingSubstitutionTag("open_tracking"))
        tracking_settings.subscription_tracking = SubscriptionTracking(
            True, SubscriptionText("Goodbye"),
            SubscriptionHtml("<strong>Goodbye!</strong>"),
            SubscriptionSubstitutionTag("unsubscribe"))
        tracking_settings.ganalytics = Ganalytics(True,
                                                  UtmSource("utm_source"),
                                                  UtmMedium("utm_medium"),
                                                  UtmTerm("utm_term"),
                                                  UtmContent("utm_content"),
                                                  UtmCampaign("utm_campaign"))
        message.tracking_settings = tracking_settings
        self.assertEqual(
            message.get(),
            json.loads(r'''{
                "asm": {
                    "group_id": 1,
                    "groups_to_display": [
                        1,
                        2,
                        3,
                        4
                    ]
                },
                "attachments": [
                    {
                        "content": "base64 encoded content 3",
                        "content_id": "Content ID 3",
                        "disposition": "inline",
                        "filename": "banner2.png",
                        "type": "image/png"
                    },
                    {
                        "content": "base64 encoded content 2",
                        "content_id": "Content ID 2",
                        "disposition": "inline",
                        "filename": "banner.png",
                        "type": "image/png"
                    },
                    {
                        "content": "base64 encoded content 1",
                        "content_id": "Content ID 1",
                        "disposition": "attachment",
                        "filename": "balance_001.pdf",
                        "type": "application/pdf"
                    }
                ],
                "batch_id": "HkJ5yLYULb7Rj8GKSx7u025ouWVlMgAi",
                "categories": [
                    "Category 2",
                    "Category 1",
                    "Category 2",
                    "Category 1"
                ],
                "content": [
                    {
                        "type": "text/plain",
                        "value": "and easy to do anywhere, even with Python"
                    },
                    {
                        "type": "text/html",
                        "value": "<strong>and easy to do anywhere, even with Python</strong>"
                    },
                    {
                        "type": "text/calendar",
                        "value": "Party Time!!"
                    },
                    {
                        "type": "text/custom",
                        "value": "Party Time 2!!"
                    }
                ],
                "custom_args": {
                    "marketing5": "false",
                    "marketing6": "true",
                    "transactional5": "true",
                    "transactional6": "false"
                },
                "from": {
                    "email": "*****@*****.**",
                    "name": "Twilio SendGrid"
                },
                "headers": {
                    "X-Test10": "Test10",
                    "X-Test11": "Test11",
                    "X-Test12": "Test12",
                    "X-Test9": "Test9"
                },
                "ip_pool_name": "IP Pool Name",
                "mail_settings": {
                    "bcc": {
                        "email": "*****@*****.**",
                        "enable": false
                    },
                    "bypass_list_management": {
                        "enable": false
                    },
                    "footer": {
                        "enable": true,
                        "html": "<string>w00t!<strong>",
                        "text": "w00t"
                    },
                    "sandbox_mode": {
                        "enable": true
                    },
                    "spam_check": {
                        "enable": true,
                        "post_to_url": "https://example.com",
                        "threshold": 5
                    }
                },
                "personalizations": [
                    {
                        "bcc": [
                            {
                                "email": "*****@*****.**",
                                "name": "Example User7"
                            },
                            {
                                "email": "*****@*****.**",
                                "name": "Example User8"
                            },
                            {
                                "email": "*****@*****.**",
                                "name": "Example User9"
                            }
                        ],
                        "cc": [
                            {
                                "email": "*****@*****.**",
                                "name": "Example User4"
                            },
                            {
                                "email": "*****@*****.**",
                                "name": "Example User5"
                            },
                            {
                                "email": "*****@*****.**",
                                "name": "Example User6"
                            }
                        ],
                        "custom_args": {
                            "marketing1": "true",
                            "marketing2": "false",
                            "transactional1": "false",
                            "transactional2": "true"
                        },
                        "headers": {
                            "X-Test1": "Test1",
                            "X-Test2": "Test2",
                            "X-Test3": "Test3",
                            "X-Test4": "Test4"
                        },
                        "send_at": 1461775051,
                        "subject": "Sending with SendGrid is Fun 0",
                        "substitutions": {
                            "%city1%": "Example City 1",
                            "%city2%": "Example City 2",
                            "%name1%": "Example Name 1",
                            "%name2%": "Example Name 2"
                        },
                        "to": [
                            {
                                "email": "*****@*****.**",
                                "name": "Example User1"
                            },
                            {
                                "email": "*****@*****.**",
                                "name": "Example User2"
                            },
                            {
                                "email": "*****@*****.**",
                                "name": "Example User3"
                            }
                        ]
                    },
                    {
                        "bcc": [
                            {
                                "email": "*****@*****.**",
                                "name": "Example User16"
                            },
                            {
                                "email": "*****@*****.**",
                                "name": "Example User17"
                            },
                            {
                                "email": "*****@*****.**",
                                "name": "Example User18"
                            }
                        ],
                        "cc": [
                            {
                                "email": "*****@*****.**",
                                "name": "Example User13"
                            },
                            {
                                "email": "*****@*****.**",
                                "name": "Example User14"
                            },
                            {
                                "email": "*****@*****.**",
                                "name": "Example User15"
                            }
                        ],
                        "custom_args": {
                            "marketing3": "true",
                            "marketing4": "false",
                            "transactional3": "false",
                            "transactional4": "true"
                        },
                        "headers": {
                            "X-Test5": "Test5",
                            "X-Test6": "Test6",
                            "X-Test7": "Test7",
                            "X-Test8": "Test8"
                        },
                        "send_at": 1461775052,
                        "subject": "Sending with SendGrid is Fun 1",
                        "substitutions": {
                            "%city3%": "Example City 3",
                            "%city4%": "Example City 4",
                            "%name3%": "Example Name 3",
                            "%name4%": "Example Name 4"
                        },
                        "to": [
                            {
                                "email": "*****@*****.**",
                                "name": "Example User10"
                            },
                            {
                                "email": "*****@*****.**",
                                "name": "Example User11"
                            },
                            {
                                "email": "*****@*****.**",
                                "name": "Example User12"
                            }
                        ]
                    }
                ],
                "reply_to": {
                    "email": "*****@*****.**",
                    "name": "Twilio SendGrid Reply"
                },
                "sections": {
                    "%section1%": "Substitution for Section 1 Tag",
                    "%section2%": "Substitution for Section 2 Tag",
                    "%section3%": "Substitution for Section 3 Tag"
                },
                "send_at": 1461775053,
                "subject": "Sending with SendGrid is Fun 2",
                "template_id": "13b8f94f-bcae-4ec6-b752-70d6cb59f932",
                "tracking_settings": {
                    "click_tracking": {
                        "enable": true,
                        "enable_text": false
                    },
                    "ganalytics": {
                        "enable": true,
                        "utm_campaign": "utm_campaign",
                        "utm_content": "utm_content",
                        "utm_medium": "utm_medium",
                        "utm_source": "utm_source",
                        "utm_term": "utm_term"
                    },
                    "open_tracking": {
                        "enable": true,
                        "substitution_tag": "open_tracking"
                    },
                    "subscription_tracking": {
                        "enable": true,
                        "html": "<strong>Goodbye!</strong>",
                        "substitution_tag": "unsubscribe",
                        "text": "Goodbye"
                    }
                }
            }'''))
Пример #10
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()
Пример #11
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()
Пример #12
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()
Пример #13
0
message.send_at = SendAt(1461775053)

message.batch_id = BatchId("HkJ5yLYULb7Rj8GKSx7u025ouWVlMgAi")

message.asm = Asm(GroupId(1), GroupsToDisplay([1, 2, 3, 4]))

message.ip_pool_name = IpPoolName("IP Pool Name")

mail_settings = MailSettings()
mail_settings.bcc_settings = BccSettings(False,
                                         BccSettingsEmail("*****@*****.**"))
mail_settings.bypass_list_management = BypassListManagement(False)
mail_settings.footer_settings = FooterSettings(
    True, FooterText("w00t"), FooterHtml("<string>w00t!<strong>"))
mail_settings.sandbox_mode = SandBoxMode(True)
mail_settings.spam_check = SpamCheck(True, SpamThreshold(5),
                                     SpamUrl("https://example.com"))
message.mail_settings = mail_settings

tracking_settings = TrackingSettings()
tracking_settings.click_tracking = ClickTracking(True, False)
tracking_settings.open_tracking = OpenTracking(
    True, OpenTrackingSubstitutionTag("open_tracking"))
tracking_settings.subscription_tracking = SubscriptionTracking(
    True, SubscriptionText("Goodbye"),
    SubscriptionHtml("<strong>Goodbye!</strong>"),
    SubscriptionSubstitutionTag("unsubscribe"))
tracking_settings.ganalytics = Ganalytics(True, UtmSource("utm_source"),
                                          UtmMedium("utm_medium"),
                                          UtmTerm("utm_term"),
Пример #14
0
        confirmation_email = Mail(
            from_email=sendgrid_from_email,
            to_emails=To(
                donor_email,
                dynamic_template_data={
                    "sum_as_concrete":
                    str(round(donation_sum / 180, 2)),
                    "sum_as_dance_floor":
                    str(round(10_000 * donation_sum / 4815)),
                    "sum_as_percentage":
                    str(round(100 * donation_sum / 6_500_00, 4)),
                    "link_to_donation":
                    f"{FRONTEND_URL}/donation?betalning=ok&checkout-transaction-id={checkout_transaction_id}"
                }))
        confirmation_email.mail_settings = MailSettings(
            sandbox_mode=SandBoxMode(enable=SENDGRID_SANDBOX_MODE))
        confirmation_email.template_id = "d-8e0408340b73439494bb26e5b6d16567"
        sendgrid_client.send(confirmation_email)
        transaction.confirmation_email_sent = True

        telegram_response = post_request_to_telegram_webhook(
            transaction.contribution.sum)
        logger.info("Sending Telegram response %s", telegram_response)
    else:
        logger.info("Confirmation email has already been sent to %s, skipping",
                    donor_email)

    logger.info("Updating payment status to OK")
    transaction.status = request.GET["checkout-status"]
    transaction.save()
Пример #15
0
def build_kitchen_sink():
    """All settings set"""
    from sendgrid.helpers.mail import (
        Mail, From, To, Cc, Bcc, Subject, PlainTextContent, 
        HtmlContent, SendGridException, Substitution, 
        Header, CustomArg, SendAt, Content, MimeType, Attachment,
        FileName, FileContent, FileType, Disposition, ContentId,
        TemplateId, Section, ReplyTo, Category, BatchId, Asm,
        GroupId, GroupsToDisplay, IpPoolName, MailSettings,
        BccSettings, BccSettingsEmail, BypassListManagement,
        FooterSettings, FooterText, FooterHtml, SandBoxMode,
        SpamCheck, SpamThreshold, SpamUrl, TrackingSettings,
        ClickTracking, SubscriptionTracking, SubscriptionText,
        SubscriptionHtml, SubscriptionSubstitutionTag,
        OpenTracking, OpenTrackingSubstitutionTag, Ganalytics,
        UtmSource, UtmMedium, UtmTerm, UtmContent, UtmCampaign)
    import time
    import datetime

    message = Mail()

    # Define Personalizations 

    message.to = To('*****@*****.**', 'Example User1', p=0)
    message.to = [ 
        To('*****@*****.**', 'Example User2', p=0),
        To('*****@*****.**', 'Example User3', p=0)
    ]

    message.cc = Cc('*****@*****.**', 'Example User4', p=0)
    message.cc = [ 
        Cc('*****@*****.**', 'Example User5', p=0),
        Cc('*****@*****.**', 'Example User6', p=0)
    ]

    message.bcc = Bcc('*****@*****.**', 'Example User7', p=0)
    message.bcc = [ 
        Bcc('*****@*****.**', 'Example User8', p=0),
        Bcc('*****@*****.**', 'Example User9', p=0)
    ]

    message.subject = Subject('Sending with SendGrid is Fun 0', p=0)

    message.header = Header('X-Test1', 'Test1', p=0)
    message.header = Header('X-Test2', 'Test2', p=0)
    message.header = [
        Header('X-Test3', 'Test3', p=0),
        Header('X-Test4', 'Test4', p=0)
    ]

    message.substitution = Substitution('%name1%', 'Example Name 1', p=0)
    message.substitution = Substitution('%city1%', 'Example City 1', p=0)
    message.substitution = [
        Substitution('%name2%', 'Example Name 2', p=0),
        Substitution('%city2%', 'Example City 2', p=0)
    ]

    message.custom_arg = CustomArg('marketing1', 'true', p=0)
    message.custom_arg = CustomArg('transactional1', 'false', p=0)
    message.custom_arg = [
        CustomArg('marketing2', 'false', p=0),
        CustomArg('transactional2', 'true', p=0)
    ]

    message.send_at = SendAt(1461775051, p=0)

    message.to = To('*****@*****.**', 'Example User10', p=1)
    message.to = [ 
        To('*****@*****.**', 'Example User11', p=1),
        To('*****@*****.**', 'Example User12', p=1)
    ]

    message.cc = Cc('*****@*****.**', 'Example User13', p=1)
    message.cc = [ 
        Cc('*****@*****.**', 'Example User14', p=1),
        Cc('*****@*****.**', 'Example User15', p=1)
    ]

    message.bcc = Bcc('*****@*****.**', 'Example User16', p=1)
    message.bcc = [ 
        Bcc('*****@*****.**', 'Example User17', p=1),
        Bcc('*****@*****.**', 'Example User18', p=1)
    ]

    message.header = Header('X-Test5', 'Test5', p=1)
    message.header = Header('X-Test6', 'Test6', p=1)
    message.header = [
        Header('X-Test7', 'Test7', p=1),
        Header('X-Test8', 'Test8', p=1)
    ]

    message.substitution = Substitution('%name3%', 'Example Name 3', p=1)
    message.substitution = Substitution('%city3%', 'Example City 3', p=1)
    message.substitution = [
        Substitution('%name4%', 'Example Name 4', p=1),
        Substitution('%city4%', 'Example City 4', p=1)
    ]

    message.custom_arg = CustomArg('marketing3', 'true', p=1)
    message.custom_arg = CustomArg('transactional3', 'false', p=1)
    message.custom_arg = [
        CustomArg('marketing4', 'false', p=1),
        CustomArg('transactional4', 'true', p=1)
    ]

    message.send_at = SendAt(1461775052, p=1)

    message.subject = Subject('Sending with SendGrid is Fun 1', p=1)

    # The values below this comment are global to entire message

    message.from_email = From('*****@*****.**', 'DX')

    message.reply_to = ReplyTo('*****@*****.**', 'DX Reply')

    message.subject = Subject('Sending with SendGrid is Fun 2')

    message.content = Content(MimeType.text, 'and easy to do anywhere, even with Python')
    message.content = Content(MimeType.html, '<strong>and easy to do anywhere, even with Python</strong>')
    message.content = [
        Content('text/calendar', 'Party Time!!'),
        Content('text/custom', 'Party Time 2!!')
    ]

    message.attachment = Attachment(FileContent('base64 encoded content 1'),
                                    FileType('application/pdf'),
                                    FileName('balance_001.pdf'),
                                    Disposition('attachment'),
                                    ContentId('Content ID 1'))
    message.attachment = [
        Attachment(FileContent('base64 encoded content 2'),
                FileType('image/png'),
                FileName('banner.png'),
                Disposition('inline'),
                ContentId('Content ID 2')),
        Attachment(FileContent('base64 encoded content 3'),
                FileType('image/png'),
                FileName('banner2.png'),
                Disposition('inline'),
                ContentId('Content ID 3'))
    ]

    message.template_id = TemplateId('13b8f94f-bcae-4ec6-b752-70d6cb59f932')

    message.section = Section('%section1%', 'Substitution for Section 1 Tag')
    message.section = [
        Section('%section2%', 'Substitution for Section 2 Tag'),
        Section('%section3%', 'Substitution for Section 3 Tag')    
    ]

    message.header = Header('X-Test9', 'Test9')
    message.header = Header('X-Test10', 'Test10')
    message.header = [
        Header('X-Test11', 'Test11'),
        Header('X-Test12', 'Test12')
    ]

    message.category = Category('Category 1')
    message.category = Category('Category 2')
    message.category = [
        Category('Category 1'),
        Category('Category 2')
    ]

    message.custom_arg = CustomArg('marketing5', 'false')
    message.custom_arg = CustomArg('transactional5', 'true')
    message.custom_arg = [
        CustomArg('marketing6', 'true'),
        CustomArg('transactional6', 'false')
    ]

    message.send_at = SendAt(1461775053)

    message.batch_id = BatchId("HkJ5yLYULb7Rj8GKSx7u025ouWVlMgAi")

    message.asm = Asm(GroupId(1), GroupsToDisplay([1,2,3,4]))

    message.ip_pool_name = IpPoolName("IP Pool Name")

    mail_settings = MailSettings()
    mail_settings.bcc_settings = BccSettings(False, BccSettingsEmail("*****@*****.**"))
    mail_settings.bypass_list_management = BypassListManagement(False)
    mail_settings.footer_settings = FooterSettings(True, FooterText("w00t"), FooterHtml("<string>w00t!<strong>"))
    mail_settings.sandbox_mode = SandBoxMode(True)
    mail_settings.spam_check = SpamCheck(True, SpamThreshold(5), SpamUrl("https://example.com"))
    message.mail_settings = mail_settings

    tracking_settings = TrackingSettings()
    tracking_settings.click_tracking = ClickTracking(True, False)
    tracking_settings.open_tracking = OpenTracking(True, OpenTrackingSubstitutionTag("open_tracking"))
    tracking_settings.subscription_tracking = SubscriptionTracking(
        True, 
        SubscriptionText("Goodbye"),
        SubscriptionHtml("<strong>Goodbye!</strong>"),
        SubscriptionSubstitutionTag("unsubscribe"))
    tracking_settings.ganalytics = Ganalytics(
        True,
        UtmSource("utm_source"),
        UtmMedium("utm_medium"),
        UtmTerm("utm_term"),
        UtmContent("utm_content"),
        UtmCampaign("utm_campaign"))
    message.tracking_settings = tracking_settings

    return message.get()
Пример #16
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()
Пример #17
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()
Пример #18
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))
Пример #19
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()