SES, SESv2: Fix get params in SESV2Response, and destinations in send_raw_email() (#6414)
This commit is contained in:
		
							parent
							
								
									4cbddbed96
								
							
						
					
					
						commit
						7b98252214
					
				| @ -2,7 +2,7 @@ import json | |||||||
| import email | import email | ||||||
| import datetime | import datetime | ||||||
| from email.mime.base import MIMEBase | from email.mime.base import MIMEBase | ||||||
| from email.utils import parseaddr | from email.utils import formataddr, getaddresses, parseaddr | ||||||
| from email.mime.multipart import MIMEMultipart | from email.mime.multipart import MIMEMultipart | ||||||
| from email.encoders import encode_7or8bit | from email.encoders import encode_7or8bit | ||||||
| from typing import Any, Dict, List, Optional | from typing import Any, Dict, List, Optional | ||||||
| @ -350,8 +350,12 @@ class SESBackend(BaseBackend): | |||||||
|                     f"Did not have authority to send from email {source}" |                     f"Did not have authority to send from email {source}" | ||||||
|                 ) |                 ) | ||||||
| 
 | 
 | ||||||
|         for header in "TO", "CC", "BCC": |         fieldvalues = [message.get(header, "") for header in ["TO", "CC", "BCC"]] | ||||||
|             destinations += [d.strip() for d in message.get(header, "").split(",") if d] |         destinations += [ | ||||||
|  |             formataddr((realname, email_address)) | ||||||
|  |             for realname, email_address in getaddresses(fieldvalues) | ||||||
|  |             if email_address | ||||||
|  |         ] | ||||||
|         if len(destinations) > RECIPIENT_LIMIT: |         if len(destinations) > RECIPIENT_LIMIT: | ||||||
|             raise MessageRejectedError("Too many recipients.") |             raise MessageRejectedError("Too many recipients.") | ||||||
|         for address in [addr for addr in [source, *destinations] if addr is not None]: |         for address in [addr for addr in [source, *destinations] if addr is not None]: | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ from moto.core.responses import BaseResponse | |||||||
| from .models import sesv2_backends | from .models import sesv2_backends | ||||||
| from ..ses.responses import SEND_EMAIL_RESPONSE | from ..ses.responses import SEND_EMAIL_RESPONSE | ||||||
| from .models import SESV2Backend | from .models import SESV2Backend | ||||||
| from typing import List, Dict, Any | from typing import List | ||||||
| from urllib.parse import unquote | from urllib.parse import unquote | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -56,7 +56,7 @@ class SESV2Response(BaseResponse): | |||||||
|         return template.render(message=message) |         return template.render(message=message) | ||||||
| 
 | 
 | ||||||
|     def create_contact_list(self) -> str: |     def create_contact_list(self) -> str: | ||||||
|         params = get_params_dict(self.data) |         params = json.loads(self.body) | ||||||
|         self.sesv2_backend.create_contact_list(params) |         self.sesv2_backend.create_contact_list(params) | ||||||
|         return json.dumps({}) |         return json.dumps({}) | ||||||
| 
 | 
 | ||||||
| @ -76,7 +76,7 @@ class SESV2Response(BaseResponse): | |||||||
| 
 | 
 | ||||||
|     def create_contact(self) -> str: |     def create_contact(self) -> str: | ||||||
|         contact_list_name = self._get_param("ContactListName") |         contact_list_name = self._get_param("ContactListName") | ||||||
|         params = get_params_dict(self.data) |         params = json.loads(self.body) | ||||||
|         self.sesv2_backend.create_contact(contact_list_name, params) |         self.sesv2_backend.create_contact(contact_list_name, params) | ||||||
|         return json.dumps({}) |         return json.dumps({}) | ||||||
| 
 | 
 | ||||||
| @ -96,8 +96,3 @@ class SESV2Response(BaseResponse): | |||||||
|         contact_list_name = self._get_param("ContactListName") |         contact_list_name = self._get_param("ContactListName") | ||||||
|         self.sesv2_backend.delete_contact(unquote(email), contact_list_name) |         self.sesv2_backend.delete_contact(unquote(email), contact_list_name) | ||||||
|         return json.dumps({}) |         return json.dumps({}) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def get_params_dict(odict: Dict[str, Any]) -> Any: |  | ||||||
|     # parsing of these params is nasty, hopefully there is a tidier way |  | ||||||
|     return json.loads(list(dict(odict.items()).keys())[0]) |  | ||||||
|  | |||||||
| @ -102,6 +102,41 @@ def test_send_raw_email__with_specific_message( | |||||||
|         assert msg.destinations == ["to@example.com", "foo@example.com"] |         assert msg.destinations == ["to@example.com", "foo@example.com"] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @mock_sesv2 | ||||||
|  | def test_send_raw_email__with_to_address_display_name( | ||||||
|  |     ses_v1, | ||||||
|  | ):  # pylint: disable=redefined-outer-name | ||||||
|  |     # Setup | ||||||
|  |     conn = boto3.client("sesv2", region_name="us-east-1") | ||||||
|  |     message = get_raw_email() | ||||||
|  |     # This particular message means that to-address with display-name which contains many ',' | ||||||
|  |     del message["To"] | ||||||
|  |     display_name = ",".join(["c" for _ in range(50)]) | ||||||
|  |     message["To"] = f""""{display_name}" <to@example.com>, foo@example.com""" | ||||||
|  |     kwargs = dict( | ||||||
|  |         Content={"Raw": {"Data": message.as_bytes()}}, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     # Execute | ||||||
|  |     ses_v1.verify_email_identity(EmailAddress="test@example.com") | ||||||
|  |     conn.send_email(**kwargs) | ||||||
|  | 
 | ||||||
|  |     # Verify | ||||||
|  |     send_quota = ses_v1.get_send_quota() | ||||||
|  |     sent_count = int(send_quota["SentLast24Hours"]) | ||||||
|  |     assert sent_count == 2 | ||||||
|  | 
 | ||||||
|  |     if not settings.TEST_SERVER_MODE: | ||||||
|  |         backend = ses_backends[DEFAULT_ACCOUNT_ID]["us-east-1"] | ||||||
|  |         msg: RawMessage = backend.sent_messages[0] | ||||||
|  |         assert message.as_bytes() == msg.raw_data.encode("utf-8") | ||||||
|  |         assert msg.source == "test@example.com" | ||||||
|  |         assert msg.destinations == [ | ||||||
|  |             """"c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c" <to@example.com>""", | ||||||
|  |             "foo@example.com", | ||||||
|  |         ] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @mock_sesv2 | @mock_sesv2 | ||||||
| def test_create_contact_list(): | def test_create_contact_list(): | ||||||
|     # Setup |     # Setup | ||||||
| @ -119,6 +154,30 @@ def test_create_contact_list(): | |||||||
|     assert result["ContactLists"][0]["ContactListName"] == contact_list_name |     assert result["ContactLists"][0]["ContactListName"] == contact_list_name | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @mock_sesv2 | ||||||
|  | def test_create_contact_list__with_topics(): | ||||||
|  |     # Setup | ||||||
|  |     conn = boto3.client("sesv2", region_name="us-east-1") | ||||||
|  |     contact_list_name = "test3" | ||||||
|  | 
 | ||||||
|  |     # Execute | ||||||
|  |     conn.create_contact_list( | ||||||
|  |         ContactListName=contact_list_name, | ||||||
|  |         Topics=[ | ||||||
|  |             { | ||||||
|  |                 "TopicName": "test-topic", | ||||||
|  |                 "DisplayName": "display=name", | ||||||
|  |                 "DefaultSubscriptionStatus": "OPT_OUT", | ||||||
|  |             } | ||||||
|  |         ], | ||||||
|  |     ) | ||||||
|  |     result = conn.list_contact_lists() | ||||||
|  | 
 | ||||||
|  |     # Verify | ||||||
|  |     assert len(result["ContactLists"]) == 1 | ||||||
|  |     assert result["ContactLists"][0]["ContactListName"] == contact_list_name | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @mock_sesv2 | @mock_sesv2 | ||||||
| def test_list_contact_lists(): | def test_list_contact_lists(): | ||||||
|     # Setup |     # Setup | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user