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

Added mail forward operations #57

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
125 changes: 125 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@
- [The **Nameserver** class](#the-nameserver-class)
- [List nameservers for a domain](#list-nameservers-for-a-domain)
- [Update nameservers for a domain](#update-nameservers-for-a-domain)
- [Mail Forwards](#mail-forwards)
- [The **MailForward** class](#the-mailforward-class)
- [List all mail forwards for a domain](#list-all-mail-forwards)
- [Get mail forward by id](#get-mail-forward-by-id)
- [Add a new mail forward](#add-a-new-mail-forward)
- [Update a mail forward](#update-a-mail-forward)
- [Delete a mail forward](#delete-a-mail-forward)
- [VPS](#vps)
- [HA-IP](#ha-ip)
- [Colocation](#colocation)
Expand Down Expand Up @@ -704,6 +711,124 @@ nameserver[0].ipv4 = '195.135.195.195'
domain.nameservers.replace(nameservers)
```

### Mail Forwards
### The **MailForward** class
When listing all mail forwards for a domain, a list of **transip.v6.objects.MailForward** objects is returned.

**_class_ MailForward**

The **MailForward** class makes the following attributes available:

- **id**: The mail forward identifier.
- **localPart**: The local part of the mailbox for the forward.
- **domain**: The domain to which the forward applies.
- **status**: Status of the forward
- **forwardTo**: The email address to forward to.

The class has the following methods:

- **delete()** will delete the mail forward
- **update()** will send the updated attributes to the TransIP API.

#### List all mail forwards
Retrieve all mail forwards for a domain by calling **mail_forwards.list()** on a **transip.v6.objects.Domain** object.
This will return a list of **transip.v6.objects.MailForward** objects.

For example:
```python
import transip
# Initialize a client using the TransIP demo token.
client = transip.TransIP(access_token=transip.v6.DEMO_TOKEN)

# List all mail forwards for a domain.
domain = client.domains.get("transipdemonstratie.nl")
mail_forwards = domain.mail_forwards.list()

# Show mail forwards
for mail_forward in mail_forwards:
print(f"id: {mail_forward.id}, Domain: {mail_forward.domain}, forwardTo: {mail_forward.forwardTo}, "
f"localPart: {mail_forward.localPart}, status: {mail_forward.status}")
```

#### Get mail forward by id
Retrieve a single mail forward by its ID by calling **mail_forwards.get()** on a **transip.v6.objects.Domain** object.
This will return a **transip.v6.objects.MailForward** object.

For example:
```python
import transip
# Initialize a client using the TransIP demo token.
client = transip.TransIP(access_token=transip.v6.DEMO_TOKEN)
domain = client.domains.get("transipdemonstratie.nl")

# Retrieve a mail forward by its ID.
mail_forward = domain.mail_forwards.get(123)

print(f"id: {mail_forward.id}, Domain: {mail_forward.domain}, forwardTo: {mail_forward.forwardTo}, "
f"localPart: {mail_forward.localPart}, status: {mail_forward.status}")
```

#### Add a new mail forward
Add a new mail forward by calling **mail_forwards.create(_data_)** on a **transip.v6.objects.Domain** object.
The **data** keyword argument requires a dictionary with the **localPart** and **forwardTo** attributes.

**Note:** Providing an empty string as the `localPart` creates a catch-all address

For example:
```python
import transip
# Initialize a client using the TransIP demo token.
client = transip.TransIP(access_token=transip.v6.DEMO_TOKEN)

# Data used to create a new mail forward.
forward_data = {
"localPart": "forward",
"forwardTo": "[email protected]"
}

domain = client.domains.get("transipdemonstratie.nl")
domain.mail_forwards.create(forward_data)
```

#### Update a mail forward
Update an existing mail forward by calling **mail_forwards.update(_id_, _data_)** on a **transip.v6.objects.Domain** object.

For example:
```python
import transip
# Initialize a client using the TransIP demo token.
client = transip.TransIP(access_token=transip.v6.DEMO_TOKEN)

# Data used to create a new mail forward.
forward_data = {
"localPart": "forward",
"forwardTo": "[email protected]"
}

# Update mail forward with id 123.
domain = client.domains.get("transipdemonstratie.nl")
domain.mail_forwards.update(123, forward_data)
```

The **transip.v6.objects.MailForward** class also provides an **update()** method to update a **MailForward** object
from an instance after changing any of the update-able attributes.

#### Delete a mail forward
Delete an existing mail forward by calling **mail_forwards.delete(_id_)** on a **transip.v6.objects.Domain** object.
The **id** keyword argument is the ID of the mail forward provided by TransIP.

For example:
```python
import transip
# Initialize a client using the TransIP demo token.
client = transip.TransIP(access_token=transip.v6.DEMO_TOKEN)

domain = client.domains.get("transipdemonstratie.nl")
domain.mail_forwards.delete(224063)
```

The **transip.v6.objects.MailForward** class also provides a **delete()** method to delete a **MailForward** object from an instance.

## VPS
The documentation for managing **VPSs** and related resources has not yet been documented. Feel free to file an [issue](https://github.com/roaldnefs/python-transip/issues/new/choose) for adding the missing section(s) in the documentation.

Expand Down
58 changes: 58 additions & 0 deletions tests/fixtures/domains.json
Original file line number Diff line number Diff line change
Expand Up @@ -353,5 +353,63 @@
}
]
}
},
{
"method": "GET",
"url": "https://api.transip.nl/v6/email/example.com/mail-forwards",
"json": {
"forwards": [
{
"id": 123,
"localPart": "forward_mailbox",
"domain": "example.com",
"status": "ready",
"forwardTo": "[email protected]"
}
]
},
"status": 200,
"content_type": "application/json"
},
{
"method": "GET",
"url": "https://api.transip.nl/v6/email/example.com/mail-forwards/123",
"json": {
"forward": {
"id": 123,
"localPart": "forward_mailbox",
"domain": "example.com",
"status": "ready",
"forwardTo": "[email protected]"
}
},
"status": 200,
"content_type": "application/json"
},
{
"method": "POST",
"url": "https://api.transip.nl/v6/email/example.com/mail-forwards",
"status": 201,
"content_type": "application/json",
"match_json_params": {
"localPart": "different_local_part",
"forwardTo": "[email protected]"
}
},
{
"method": "PUT",
"url": "https://api.transip.nl/v6/email/example.com/mail-forwards/123",
"status": 204,
"content_type": "application/json",
"match_json_params": {
"localPart": "different_local_part",
"forwardTo": "[email protected]"
}
},
{
"method": "DELETE",
"url": "https://api.transip.nl/v6/email/example.com/mail-forwards/123",
"status": 204,
"content_type": "application/json"
}
]
83 changes: 81 additions & 2 deletions tests/services/test_domains.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from typing import List, Dict, Any, Union

from transip import TransIP
from transip.v6.objects import Domain, WhoisContact, Nameserver, DnsEntry
from transip.v6.objects import Domain, WhoisContact, Nameserver, DnsEntry, MailForward, MailForwardService
from tests.utils import load_responses_fixtures


Expand Down Expand Up @@ -120,7 +120,6 @@ def test_dns_replace(self) -> None:
except Exception as exc:
assert False, f"'transip.v6.objects.Domain.dns.replace' raised an exception {exc}"


@responses.activate
def test_dns_create(self) -> None:
dns_entry_data: Dict[str, Union[str, int]] = {
Expand Down Expand Up @@ -215,3 +214,83 @@ def test_dns_delete_object(self) -> None:
# the listing of the DNS entries and the deletion of a single DNS
# entry.
self.assertEqual(len(responses.calls), 3)

@responses.activate
def test_mail_forwards_list(self) -> None:
"""
Check if the mail forwards of a single domain can be listed.
"""
domain: Domain = self.client.domains.get("example.com") # type: ignore
mail_forwards: List[MailForward] = domain.mail_forwards.list() # type: ignore
self.assertEqual(len(mail_forwards), 1)

forward: MailForward = mail_forwards[0]

self.assertEqual(forward.get_id(), 123) # type: ignore

@responses.activate
def test_mail_forwards_get(self) -> None:
forward_id: int = 123

domain: Domain = self.client.domains.get("example.com") # type: ignore
forward: MailForward = domain.mail_forwards.get(forward_id) # type: ignore

self.assertEqual(forward.get_id(), forward_id) # type: ignore

@responses.activate
def test_delete(self) -> None:
forward_id: int = 123
domain: Domain = self.client.domains.get("example.com") # type: ignore

try:
domain.mail_forwards.delete(forward_id) # type: ignore
except Exception as exc:
assert False, f"'transip.TransIP.mail_forwards.delete' raised an exception {exc}"

@responses.activate
def test_delete_object(self) -> None:
forward_id: int = 123
forward: MailForward = self.client.domains.get("example.com").mail_forwards.get(forward_id) # type: ignore

try:
forward.delete() # type: ignore
except Exception as exc:
assert False, f"'transip.v6.objects.MailForward.delete' raised an exception {exc}"

@responses.activate
def test_update_object(self) -> None:
forward_id: int = 123
forward: MailForward = self.client.domains.get("example.com").mail_forwards.get(forward_id) # type: ignore
forward.localPart = "different_local_part"
forward.forwardTo = "[email protected]"

try:
forward.update()
except Exception as exc:
assert False, f"'transip.v6.objects.MailForward.update' raised an exception {exc}"

@responses.activate
def test_update(self) -> None:
forward_id: int = 123
mail_forward_data: Dict[str, str] = {
"localPart": "different_local_part",
"forwardTo": "[email protected]"
}

try:
self.client.domains.get("example.com").mail_forwards.update( # type: ignore
forward_id, mail_forward_data
)
except Exception as exc:
assert False, f"'transip.TransIP.mail_forwards.update' raised an exception {exc}"

@responses.activate
def test_create(self) -> None:
mail_forward_data: Dict[str, str] = {
"localPart": "different_local_part",
"forwardTo": "[email protected]"
}
self.client.domains.get("example.com").mail_forwards.create(mail_forward_data) # type: ignore

assert len(responses.calls) == 2
assert responses.calls[1].response.status_code == 201
34 changes: 34 additions & 0 deletions transip/v6/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,32 @@ class NameserverService(ListMixin, ReplaceMixin, ApiService):
)


class MailForward(ObjectUpdateMixin, ObjectDeleteMixin, ApiObject):

_id_attr: Optional[str] = "id"


class MailForwardService(GetMixin, CreateMixin, UpdateMixin, DeleteMixin,
ListMixin, ApiService):
"""Service to manage mail forwards for a domain."""

_path: str = "/email/{parent_id}/mail-forwards"
_obj_cls: Optional[Type[ApiObject]] = MailForward

_resp_list_attr: str = "forwards"
_resp_get_attr: str = "forward"

_create_attrs: Optional[AttrsTuple] = (
("localPart", "forwardTo",), # required
tuple() # optional
)

_update_attrs: Optional[AttrsTuple] = (
("localPart", "forwardTo",), # required
tuple() # optional
)


class Domain(ApiObject):

_id_attr: str = "name"
Expand Down Expand Up @@ -359,6 +385,14 @@ def nameservers(self) -> NameserverService:
parent=self # type: ignore
)

@property
def mail_forwards(self) -> MailForwardService:
"""Return the service to manage mail forwards for a domain."""
return MailForwardService(
self.service.client,
parent=self # type: ignore
)


class DomainService(CreateMixin, GetMixin, DeleteMixin, ListMixin, ApiService):
"""Service to manage domains."""
Expand Down