Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
44 changes: 44 additions & 0 deletions examples/sending.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import mailtrap as mt

API_TOKEN = "<YOU_API_TOKEN>"
INBOX_ID = "<YOUR_INBOX_ID>"


default_client = mt.MailtrapClient(token=API_TOKEN)
bulk_client = mt.MailtrapClient(token=API_TOKEN, bulk=True)
sandbox_client = mt.MailtrapClient(token=API_TOKEN, sandbox=True, inbox_id=INBOX_ID)


mail = mt.Mail(
sender=mt.Address(email="<SENDER_EMAIL>", name="<SENDER_NAME>"),
to=[mt.Address(email="<RECEIVER_EMAIL>")],
subject="You are awesome!",
text="Congrats for sending test email with Mailtrap!",
category="Integration Test",
)
mail_from_template = mt.MailFromTemplate(
sender=mt.Address(email="<SENDER_EMAIL>", name="<SENDER_NAME>"),
to=[mt.Address(email="<RECEIVER_EMAIL>")],
template_uuid="<YOUT_TEMPLATE_UUID>",
template_variables={
"company_info_name": "Test_Company_info_name",
"name": "Test_Name",
"company_info_address": "Test_Company_info_address",
"company_info_city": "Test_Company_info_city",
"company_info_zip_code": "Test_Company_info_zip_code",
"company_info_country": "Test_Company_info_country",
},
)


def send(client: mt.MailtrapClient, mail: mt.BaseMail) -> mt.SEND_ENDPOINT_RESPONSE:
return client.send(mail)


def batch_send(client: mt.MailtrapClient, mail: mt.BaseMail) -> mt.SEND_ENDPOINT_RESPONSE:
# will be added soon
pass


if __name__ == "__main__":
print(send(default_client, mail))
14 changes: 7 additions & 7 deletions mailtrap/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from .client import SEND_ENDPOINT_RESPONSE
from .client import MailtrapClient
from .exceptions import APIError
from .exceptions import AuthorizationError
from .exceptions import ClientConfigurationError
from .exceptions import MailtrapError
from .mail import Address
from .mail import Attachment
from .mail import BaseEntity
from .mail import BaseMail
from .mail import Disposition
from .mail import Mail
from .mail import MailFromTemplate
from .models.mail import Address
from .models.mail import Attachment
from .models.mail import BaseMail
from .models.mail import Disposition
from .models.mail import Mail
from .models.mail import MailFromTemplate
22 changes: 22 additions & 0 deletions mailtrap/api/sending.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import Optional

from mailtrap.http import HttpClient
from mailtrap.models.mail.base import BaseMail
from mailtrap.models.mail.base import SendingMailResponse


class SendingApi:
def __init__(self, client: HttpClient, inbox_id: Optional[str] = None) -> None:
self._inbox_id = inbox_id
self._client = client

@property
def _api_url(self) -> str:
url = "/api/send"
if self._inbox_id:
return f"{url}/{self._inbox_id}"
return url

def send(self, mail: BaseMail) -> SendingMailResponse:
response = self._client.post(self._api_url, json=mail.api_data)
return SendingMailResponse(**response)
74 changes: 38 additions & 36 deletions mailtrap/client.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
from typing import NoReturn
import warnings
from typing import Optional
from typing import Union
from typing import cast

import requests
from pydantic import TypeAdapter

from mailtrap.api.sending import SendingApi
from mailtrap.api.testing import TestingApi
from mailtrap.config import BULK_HOST
from mailtrap.config import GENERAL_HOST
from mailtrap.exceptions import APIError
from mailtrap.exceptions import AuthorizationError
from mailtrap.config import SANDBOX_HOST
from mailtrap.config import SENDING_HOST
from mailtrap.exceptions import ClientConfigurationError
from mailtrap.http import HttpClient
from mailtrap.mail.base import BaseMail
from mailtrap.models.mail import BaseMail
from mailtrap.models.mail.base import SendingMailResponse

SEND_ENDPOINT_RESPONSE = dict[str, Union[bool, list[str]]]


class MailtrapClient:
DEFAULT_HOST = "send.api.mailtrap.io"
DEFAULT_PORT = 443
BULK_HOST = "bulk.api.mailtrap.io"
SANDBOX_HOST = "sandbox.api.mailtrap.io"

def __init__(
self,
Expand Down Expand Up @@ -49,27 +51,37 @@ def testing_api(self) -> TestingApi:
client=HttpClient(host=GENERAL_HOST, headers=self.headers),
)

def send(self, mail: BaseMail) -> dict[str, Union[bool, list[str]]]:
response = requests.post(
self.api_send_url, headers=self.headers, json=mail.api_data
@property
def sending_api(self) -> SendingApi:
http_client = HttpClient(host=self._sending_api_host, headers=self.headers)
return SendingApi(client=http_client, inbox_id=self.inbox_id)

def send(self, mail: BaseMail) -> SEND_ENDPOINT_RESPONSE:
sending_response = self.sending_api.send(mail)
return cast(
SEND_ENDPOINT_RESPONSE,
TypeAdapter(SendingMailResponse).dump_python(sending_response),
)

if response.ok:
data: dict[str, Union[bool, list[str]]] = response.json()
return data

self._handle_failed_response(response)

@property
def base_url(self) -> str:
return f"https://{self._host.rstrip('/')}:{self.api_port}"
warnings.warn(
"base_url is deprecated and will be removed in a future release.",
DeprecationWarning,
stacklevel=2,
)
return f"https://{self._sending_api_host.rstrip('/')}:{self.api_port}"

@property
def api_send_url(self) -> str:
warnings.warn(
"api_send_url is deprecated and will be removed in a future release.",
DeprecationWarning,
stacklevel=2,
)
url = f"{self.base_url}/api/send"
if self.sandbox and self.inbox_id:
return f"{url}/{self.inbox_id}"

return url

@property
Expand All @@ -83,24 +95,18 @@ def headers(self) -> dict[str, str]:
}

@property
def _host(self) -> str:
def _sending_api_host(self) -> str:
if self.api_host:
return self.api_host
if self.sandbox:
return self.SANDBOX_HOST
return SANDBOX_HOST
if self.bulk:
return self.BULK_HOST
return self.DEFAULT_HOST

@staticmethod
def _handle_failed_response(response: requests.Response) -> NoReturn:
status_code = response.status_code
data = response.json()
return BULK_HOST
return SENDING_HOST

if status_code == 401:
raise AuthorizationError(data["errors"])

raise APIError(status_code, data["errors"])
def _validate_account_id(self) -> None:
if not self.account_id:
raise ClientConfigurationError("`account_id` is required for Testing API")

def _validate_itself(self) -> None:
if self.sandbox and not self.inbox_id:
Expand All @@ -113,7 +119,3 @@ def _validate_itself(self) -> None:

if self.bulk and self.sandbox:
raise ClientConfigurationError("bulk mode is not allowed in sandbox mode")

def _validate_account_id(self) -> None:
if not self.account_id:
raise ClientConfigurationError("`account_id` is required for Testing API")
3 changes: 3 additions & 0 deletions mailtrap/config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
GENERAL_HOST = "mailtrap.io"
BULK_HOST = "bulk.api.mailtrap.io"
SANDBOX_HOST = "sandbox.api.mailtrap.io"
SENDING_HOST = "send.api.mailtrap.io"

DEFAULT_REQUEST_TIMEOUT = 30 # in seconds
7 changes: 0 additions & 7 deletions mailtrap/mail/__init__.py

This file was deleted.

14 changes: 0 additions & 14 deletions mailtrap/mail/address.py

This file was deleted.

38 changes: 0 additions & 38 deletions mailtrap/mail/attachment.py

This file was deleted.

53 changes: 0 additions & 53 deletions mailtrap/mail/base.py

This file was deleted.

14 changes: 0 additions & 14 deletions mailtrap/mail/base_entity.py

This file was deleted.

45 changes: 0 additions & 45 deletions mailtrap/mail/from_template.py

This file was deleted.

Loading
Loading