Ejemplo n.º 1
0
    def send_letter(self,
                    template_id,
                    emails,
                    dynamic_template_data=None,
                    categories=None):
        categories = categories or []
        dynamic_template_data = dynamic_template_data or {}

        mail = Mail()

        mail.template_id = template_id
        mail.from_email = Email(email=settings.EMAIL_FROM,
                                name=settings.DEFAULT_FROM_EMAIL)

        for email in emails:
            personalization = Personalization()

            personalization.add_to(Email(email))
            personalization.dynamic_template_data = dynamic_template_data

            mail.add_personalization(personalization)

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

        return self._send_letter(mail.get())
def sender_new_order_status(order_queryset):
    """
    Sending an email to the client to indicate a change of status.
    """

    done = True

    for order in order_queryset:

        data = {
            'reforder': order.reference,
            'clientname': order.first_name,
            'price': order.total_price,
            'status': order.status
        }

        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_UPDATE_CMD')
        mail.subject = "Le statu de votre commande a changée"
        p = Personalization()
        p.add_to(Email(order.email, f"{order.last_name} {order.first_name}"))
        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())

        if response.status_code == 202:
            continue
        else:
            done = False

    return done
Ejemplo n.º 3
0
def send_email(
    sender=settings.CLOUDCV_TEAM_EMAIL,
    recipient=None,
    template_id=None,
    template_data={},
):
    """Function to send email

    Keyword Arguments:
        sender {string} -- Email of sender (default: {settings.TEAM_EMAIL})
        recipient {string} -- Recipient email address
        template_id {string} -- Sendgrid template id
        template_data {dict} -- Dictionary to substitute values in subject and email body
    """
    try:
        sg = sendgrid.SendGridAPIClient(
            apikey=os.environ.get("SENDGRID_API_KEY")
        )
        sender = Email(sender)
        mail = Mail()
        mail.from_email = sender
        mail.template_id = template_id
        to_list = Personalization()
        to_list.dynamic_template_data = template_data
        to_email = Email(recipient)
        to_list.add_to(to_email)
        mail.add_personalization(to_list)
        sg.client.mail.send.post(request_body=mail.get())
    except Exception:
        logger.warning(
            "Cannot make sendgrid call. Please check if SENDGRID_API_KEY is present."
        )
    return
Ejemplo n.º 4
0
def _notify(job):
    try:
        logger.debug(
            f"Sending email notification to {job.user_name} <{job.user_email}>"
        )
        sendgrid = SendGridAPIClient()
        mail = Mail()
        mail.from_email = Email("DD-DeCaF <*****@*****.**>")
        mail.template_id = "d-8caebf4f862b4c67932515c45c5404cc"
        personalization = Personalization()
        personalization.add_to(Email(job.user_email))
        personalization.dynamic_template_data = {
            "name": job.user_name,
            "product": job.product_name,
            "organism": job.organism_name,
            "results_url": f"https://caffeine.dd-decaf.eu/jobs/{job.job_id}",
        }
        mail.add_personalization(personalization)
        sendgrid.client.mail.send.post(request_body=mail.get())
    except Exception as error:
        # Suppress any problem so it doesn't mark the entire workflow as failed,
        # but do log a warning for potential follow-up.
        logger.warning(
            "Unable to send email notification upon job completion",
            exc_info=error,
        )
Ejemplo n.º 5
0
def sender_reset_password(user, host):
    """
    Send the email to the user to reset his password.
    """
    link = f"{host}/user/reset_password/"
    data = {
        "code": user.check_code,
        "link": link,
        "username": str(user)
    }

    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_RESET_PASSWORD')
    mail.subject = "Réinitialisation de mot de passe."
    p = Personalization()
    p.add_to(Email(user.email, str(user)))
    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
Ejemplo n.º 6
0
    def send_email(self):

        # send email using the self.cleaned_data dictionary
        first_name = self.cleaned_data.get("fname")
        last_name = self.cleaned_data.get("lname")
        email = self.cleaned_data.get("email")
        phone = self.cleaned_data.get("phone")
        message = self.cleaned_data.get("message")

        # Issue response to client via sendgrid API
        sendgrid_client = SendGridAPIClient(config('SENDGRID_API_KEY'))
        mail = Mail()
        mail.from_email = From(config('EMAIL_FROM'))
        mail.to_email = To(email)
        mail.subject = "Your Enquiry with Mayan Web Studio"
        mail.template_id = config('SENDGRID_TEMPLATE_ID')
        p = Personalization()
        p.add_to(To(email))
        p.dynamic_template_data = {
            "firstName": first_name,
            "lastName": last_name,
            "phone": phone
        }
        mail.add_personalization(p)

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

        # Send notification email to Mayan
        subject, from_email, to = 'New Enquiry for Mayan Web Studio', config(
            'EMAIL_FROM'), '*****@*****.**'
        text_content = 'This is an important message.'
        html_content = '''
        <h3>New Enquiry from</h3>
        <ul>
        <li>First Name: $(first_name)</li>
        <li>Last Name: $(last_name)</li>
        <li>Email: $(email)</li>
        <li>Phone: $(phone)</li>
        <li>Message: $(message)</li>
        </ul>
        '''

        html_content = html_content.replace("$(first_name)", first_name)
        html_content = html_content.replace("$(last_name)", last_name)
        html_content = html_content.replace("$(email)", email)
        html_content = html_content.replace("$(phone)", phone)
        html_content = html_content.replace("$(message)", message)

        msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
        msg.attach_alternative(html_content, "text/html")
        msg.send()
Ejemplo n.º 7
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)

        if message.mail_options and message.mail_options.get('from_name'):
            mail.from_email.name = message.mail_options.get('from_name')

        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))

                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
Ejemplo n.º 8
0
    def send_mail(self, template_id, sender, recipient, data_dict):
        mail = Mail()
        mail.template_id = template_id

        mail.from_email = Email(sender)
        personalization = Personalization()
        personalization.add_to(Email(recipient))
        personalization.dynamic_template_data = data_dict
        mail.add_personalization(personalization)

        try:
            response = sg.client.mail.send.post(request_body=mail.get())
        except exceptions.BadRequestsError as e:
            print("INSIDE")
            print(e.body)
            exit()
        print(response.status_code)
        print(response.body)
        print(response.headers)
Ejemplo n.º 9
0
def sender_activate_account(user, host):
    """
    Send the email to the user to active his account.
    """
    link = f"{host}/user/active_account?id={user.pk}&key={user.activate_key}"
    data = {"username": str(user), "link": link}

    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_ACTIVE_ACCOUNT')
    mail.subject = "Activation de compte client"
    p = Personalization()
    p.add_to(Email(user.email, str(user)))
    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
Ejemplo n.º 10
0
 def send_reset_email(self):
     token = self.get_reset_token()
     try:
         logger.debug(f"Sending email with reset link to "
                      f"{self.full_name} <{self.email}>")
         sendgrid = SendGridAPIClient()
         mail = Mail()
         mail.from_email = Email("DD-DeCaF <*****@*****.**>")
         mail.template_id = "d-f1addc67e51f4d0e8966d340c24551a4"
         personalization = Personalization()
         personalization.add_to(Email(self.email))
         personalization.dynamic_template_data = {
             "link": f"{app.config['ROOT_URL']}/password-reset/{token}"
         }
         mail.add_personalization(personalization)
         sendgrid.client.mail.send.post(request_body=mail.get())
         return '''An email has been sent with instructions
                     to reset your password.''', 200
     except Exception as error:
         logger.warning("Unable to send email with password reset link",
                        exc_info=error)
         return "Unable to send email with password reset link", 502
Ejemplo n.º 11
0
    def test_dynamic_template_data(self):
        p = Personalization()
        p.add_to(Email('*****@*****.**'))
        p.dynamic_template_data = {
            'customer': {
                'name': 'Bob',
                'returning': True
                },
            'total': 42
            }

        expected = {
            'to': [{'email': '*****@*****.**'}],
            'dynamic_template_data': {
                'customer': {
                    'name': 'Bob',
                    'returning': True
                    },
                'total': 42
                }
        }
        self.assertDictEqual(p.get(), expected)
    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))

                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)

        return mail
Ejemplo n.º 13
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()
Ejemplo n.º 14
0
    def _build_sg_personalization(
        self,
        msg: EmailMessage,
        extra_headers: Iterable[Header],
        to: Optional[List[str]] = None,
        existing_personalizations: Optional[Personalization] = None,
    ) -> Personalization:
        """
        Constructs a Sendgrid Personalization instance / row for the given recipients.

        If no "per row" personalizations are provided, the personalization data is populated
        from msg.

        Args:
            msg: The base Django Email message object - used to fill (missing) personalization data
            extra_headers: The non "reply-to" headers for the personalization.
            to: The email addresses for the given personalization.
            existing_personalizations: Personalization data, eg. dynamic_template_data or substitutions.
                A given value should have key equivalent to the corresponding EmailMessage attr


        Returns:
            A sendgrid personalization instance
        """

        if existing_personalizations is None:
            if not to:
                raise ValueError(
                    "Either msg.to or msg.personalizations (with recipients) must be set"
                )

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

        elif existing_personalizations.tos:
            personalization = existing_personalizations
        else:
            raise ValueError("Each msg personalization must have recipients")

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

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

        if not personalization.custom_args:
            for k, v in getattr(msg, "custom_args", {}).items():
                personalization.add_custom_arg(CustomArg(k, v))

        if self._is_transaction_template(msg):
            if personalization.subject or 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

        if not personalization.subject:
            personalization.subject = msg.subject

        for header in extra_headers:
            personalization.add_header(header)

        # 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, "template_id"):
            if not personalization.substitutions:
                for k, v in getattr(msg, "substitutions", {}).items():
                    personalization.add_substitution(Substitution(k, v))

            dtd = personalization.dynamic_template_data or getattr(
                msg, "dynamic_template_data", None)
            if dtd:
                if SENDGRID_5:
                    logger.warning(
                        "dynamic_template_data not available in sendgrid version < 6"
                    )
                else:
                    personalization.dynamic_template_data = dtd

        return personalization
Ejemplo n.º 15
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
Ejemplo n.º 16
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()
Ejemplo n.º 17
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()
Ejemplo n.º 18
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

        # 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()