Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encoding unicode in "friendly-from" field #1990

Merged
merged 6 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions app/clients/email/aws_ses.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from time import monotonic
import base64
Fixed Show fixed Hide fixed

import boto3
import botocore
from flask import current_app
from notifications_utils.recipients import InvalidEmailError
from notifications_utils.statsd_decorators import statsd
from unidecode import unidecode
# from unidecode import unidecode

from app.clients.email import EmailClient, EmailClientException

Expand Down Expand Up @@ -63,7 +64,9 @@
attachments = attachments or []
if isinstance(to_addresses, str):
to_addresses = [to_addresses]
source = unidecode(source)
# TODO: fix this to allow accents
# source = base64.b64encode(bytes(source, "utf-8"))

reply_to_addresses = [reply_to_address] if reply_to_address else []

# - If sending a TXT email without attachments:
Expand Down Expand Up @@ -101,8 +104,10 @@
msg.attach(attachment_part)

start_time = monotonic()
response = self._client.send_raw_email(Source=source, RawMessage={"Data": msg.as_string()})
response = self._client.send_raw_email(RawMessage={"Data": msg.as_string()})
except botocore.exceptions.ClientError as e:
# got an error here using a service with accents in the name

self.statsd_client.incr("clients.ses.error")

# http://docs.aws.amazon.com/ses/latest/DeveloperGuide/api-error-codes.html
Expand Down
21 changes: 18 additions & 3 deletions app/delivery/send_to_providers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import base64
import os
import re
import urllib.request
from datetime import datetime
from typing import Dict
from uuid import UUID
from unidecode import unidecode

from flask import current_app
from notifications_utils.recipients import (
Expand Down Expand Up @@ -266,9 +268,22 @@ def send_email_to_provider(notification: Notification):
sending_domain = current_app.config["NOTIFY_EMAIL_DOMAIN"]
else:
sending_domain = service.sending_domain

from_address = '"{}" <{}@{}>'.format(service.name, service.email_from, sending_domain)


# do not use unidecode for the service name as it may contain accents
# https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ses/client/send_raw_email.html
# Amazon SES does not support the SMTPUTF8 extension, as described in RFC6531. For this reason,
# the email address string must be 7-bit ASCII. If you want to send to or from email addresses that contain
# Unicode characters in the domain part of an address, you must encode the domain using Punycode.
# Punycode is not permitted in the local part of the email address (the part before the @ sign) nor in the “friendly from” name.
# If you want to use Unicode characters in the “friendly from” name, you must encode the “friendly from” name using
# MIME encoded-word syntax, as described in Sending raw email using the Amazon SES API. For more information about Punycode,
# see RFC 3492.

service_name = service.name
x = base64.b64encode(service_name.encode()).decode("utf-8")
friendly_from = f"=?utf-8?B?{x}?="
from_address = f'"{friendly_from}" <{unidecode(service.email_from)}@{unidecode(sending_domain)}>'

email_reply_to = notification.reply_to_text

reference = provider.send_email(
Expand Down
Loading