11from typing import NoReturn
2+ from typing import Optional
23from typing import Union
34
45import requests
56
67from mailtrap .exceptions import APIError
78from mailtrap .exceptions import AuthorizationError
9+ from mailtrap .exceptions import ClientConfigurationError
810from mailtrap .mail .base import BaseMail
911
1012
1113class MailtrapClient :
1214 DEFAULT_HOST = "send.api.mailtrap.io"
1315 DEFAULT_PORT = 443
16+ BULK_HOST = "bulk.api.mailtrap.io"
17+ SANDBOX_HOST = "sandbox.api.mailtrap.io"
1418
1519 def __init__ (
1620 self ,
1721 token : str ,
18- api_host : str = DEFAULT_HOST ,
22+ api_host : Optional [ str ] = None ,
1923 api_port : int = DEFAULT_PORT ,
24+ bulk : bool = False ,
25+ sandbox : bool = False ,
26+ inbox_id : Optional [str ] = None ,
2027 ) -> None :
2128 self .token = token
2229 self .api_host = api_host
2330 self .api_port = api_port
31+ self .bulk = bulk
32+ self .sandbox = sandbox
33+ self .inbox_id = inbox_id
34+
35+ self ._validate_itself ()
2436
2537 def send (self , mail : BaseMail ) -> dict [str , Union [bool , list [str ]]]:
26- url = f"{ self .base_url } /api/send"
27- response = requests .post (url , headers = self .headers , json = mail .api_data )
38+ response = requests .post (
39+ self .api_send_url , headers = self .headers , json = mail .api_data
40+ )
2841
2942 if response .ok :
3043 data : dict [str , Union [bool , list [str ]]] = response .json ()
@@ -34,7 +47,15 @@ def send(self, mail: BaseMail) -> dict[str, Union[bool, list[str]]]:
3447
3548 @property
3649 def base_url (self ) -> str :
37- return f"https://{ self .api_host .rstrip ('/' )} :{ self .api_port } "
50+ return f"https://{ self ._host .rstrip ('/' )} :{ self .api_port } "
51+
52+ @property
53+ def api_send_url (self ) -> str :
54+ url = f"{ self .base_url } /api/send"
55+ if self .sandbox and self .inbox_id :
56+ return f"{ url } /{ self .inbox_id } "
57+
58+ return url
3859
3960 @property
4061 def headers (self ) -> dict [str , str ]:
@@ -46,6 +67,16 @@ def headers(self) -> dict[str, str]:
4667 ),
4768 }
4869
70+ @property
71+ def _host (self ) -> str :
72+ if self .api_host :
73+ return self .api_host
74+ if self .sandbox :
75+ return self .SANDBOX_HOST
76+ if self .bulk :
77+ return self .BULK_HOST
78+ return self .DEFAULT_HOST
79+
4980 @staticmethod
5081 def _handle_failed_response (response : requests .Response ) -> NoReturn :
5182 status_code = response .status_code
@@ -55,3 +86,15 @@ def _handle_failed_response(response: requests.Response) -> NoReturn:
5586 raise AuthorizationError (data ["errors" ])
5687
5788 raise APIError (status_code , data ["errors" ])
89+
90+ def _validate_itself (self ) -> None :
91+ if self .sandbox and not self .inbox_id :
92+ raise ClientConfigurationError ("`inbox_id` is required for sandbox mode" )
93+
94+ if not self .sandbox and self .inbox_id :
95+ raise ClientConfigurationError (
96+ "`inbox_id` is not allowed in non-sandbox mode"
97+ )
98+
99+ if self .bulk and self .sandbox :
100+ raise ClientConfigurationError ("bulk mode is not allowed in sandbox mode" )
0 commit comments