retab 0.0.42__py3-none-any.whl → 0.0.44__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- retab/__init__.py +2 -1
- retab/client.py +26 -51
- retab/generate_types.py +180 -0
- retab/resources/consensus/client.py +1 -1
- retab/resources/consensus/responses.py +1 -1
- retab/resources/deployments/__init__.py +3 -0
- retab/resources/deployments/automations/__init__.py +9 -0
- retab/resources/deployments/automations/client.py +244 -0
- retab/resources/deployments/automations/endpoints.py +290 -0
- retab/resources/deployments/automations/links.py +303 -0
- retab/resources/deployments/automations/logs.py +222 -0
- retab/resources/deployments/automations/mailboxes.py +423 -0
- retab/resources/deployments/automations/outlook.py +377 -0
- retab/resources/deployments/automations/tests.py +161 -0
- retab/resources/deployments/client.py +148 -0
- retab/resources/documents/client.py +94 -68
- retab/resources/documents/extractions.py +55 -46
- retab/resources/evaluations/__init__.py +2 -2
- retab/resources/evaluations/client.py +61 -77
- retab/resources/evaluations/documents.py +48 -37
- retab/resources/evaluations/iterations.py +58 -40
- retab/resources/jsonlUtils.py +3 -4
- retab/resources/processors/automations/endpoints.py +49 -39
- retab/resources/processors/automations/links.py +52 -43
- retab/resources/processors/automations/mailboxes.py +74 -59
- retab/resources/processors/automations/outlook.py +104 -82
- retab/resources/processors/client.py +35 -30
- retab/resources/projects/__init__.py +3 -0
- retab/resources/projects/client.py +285 -0
- retab/resources/projects/documents.py +244 -0
- retab/resources/projects/iterations.py +470 -0
- retab/resources/usage.py +2 -0
- retab/types/ai_models.py +2 -1
- retab/types/deprecated_evals.py +195 -0
- retab/types/evaluations/__init__.py +5 -2
- retab/types/evaluations/iterations.py +9 -43
- retab/types/evaluations/model.py +19 -24
- retab/types/extractions.py +1 -0
- retab/types/jobs/base.py +1 -1
- retab/types/jobs/evaluation.py +1 -1
- retab/types/logs.py +5 -6
- retab/types/mime.py +1 -10
- retab/types/projects/__init__.py +34 -0
- retab/types/projects/documents.py +30 -0
- retab/types/projects/iterations.py +78 -0
- retab/types/projects/model.py +68 -0
- retab/types/schemas/enhance.py +22 -5
- retab/types/schemas/evaluate.py +2 -2
- retab/types/schemas/object.py +27 -25
- retab/types/standards.py +2 -2
- retab/utils/__init__.py +3 -0
- retab/utils/ai_models.py +127 -12
- retab/utils/hashing.py +24 -0
- retab/utils/json_schema.py +1 -26
- retab/utils/mime.py +0 -17
- retab/utils/usage/usage.py +0 -1
- {retab-0.0.42.dist-info → retab-0.0.44.dist-info}/METADATA +4 -6
- {retab-0.0.42.dist-info → retab-0.0.44.dist-info}/RECORD +60 -55
- retab/_utils/__init__.py +0 -0
- retab/_utils/_model_cards/anthropic.yaml +0 -59
- retab/_utils/_model_cards/auto.yaml +0 -43
- retab/_utils/_model_cards/gemini.yaml +0 -117
- retab/_utils/_model_cards/openai.yaml +0 -301
- retab/_utils/_model_cards/xai.yaml +0 -28
- retab/_utils/ai_models.py +0 -138
- retab/_utils/benchmarking.py +0 -484
- retab/_utils/chat.py +0 -327
- retab/_utils/display.py +0 -440
- retab/_utils/json_schema.py +0 -2156
- retab/_utils/mime.py +0 -165
- retab/_utils/responses.py +0 -169
- retab/_utils/stream_context_managers.py +0 -52
- retab/_utils/usage/__init__.py +0 -0
- retab/_utils/usage/usage.py +0 -301
- {retab-0.0.42.dist-info → retab-0.0.44.dist-info}/WHEEL +0 -0
- {retab-0.0.42.dist-info → retab-0.0.44.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,222 @@
|
|
1
|
+
from typing import Literal, Optional
|
2
|
+
|
3
|
+
from ...._resource import AsyncAPIResource, SyncAPIResource
|
4
|
+
from ....types.logs import AutomationLog, ExternalRequestLog, ListLogs
|
5
|
+
from ....types.standards import PreparedRequest
|
6
|
+
|
7
|
+
|
8
|
+
class LogsMixin:
|
9
|
+
def prepare_get(self, processor_id: str, log_id: str) -> PreparedRequest:
|
10
|
+
"""Get a specific automation log by ID.
|
11
|
+
|
12
|
+
Args:
|
13
|
+
processor_id: ID of the processor
|
14
|
+
log_id: ID of the log to retrieve
|
15
|
+
|
16
|
+
Returns:
|
17
|
+
PreparedRequest: The prepared request
|
18
|
+
"""
|
19
|
+
return PreparedRequest(method="GET", url=f"/v1/processors/{processor_id}/automations/logs/{log_id}")
|
20
|
+
|
21
|
+
def prepare_list(
|
22
|
+
self,
|
23
|
+
processor_id: str,
|
24
|
+
before: Optional[str] = None,
|
25
|
+
after: Optional[str] = None,
|
26
|
+
limit: Optional[int] = 10,
|
27
|
+
order: Optional[Literal["asc", "desc"]] = "desc",
|
28
|
+
# Filtering parameters
|
29
|
+
status_code: Optional[int] = None,
|
30
|
+
status_class: Optional[Literal["2xx", "3xx", "4xx", "5xx"]] = None,
|
31
|
+
automation_id: Optional[str] = None,
|
32
|
+
webhook_url: Optional[str] = None,
|
33
|
+
schema_id: Optional[str] = None,
|
34
|
+
schema_data_id: Optional[str] = None,
|
35
|
+
) -> PreparedRequest:
|
36
|
+
"""List automation logs with pagination support.
|
37
|
+
|
38
|
+
Args:
|
39
|
+
processor_id: ID of the processor
|
40
|
+
before: Optional cursor for pagination before a specific log ID
|
41
|
+
after: Optional cursor for pagination after a specific log ID
|
42
|
+
limit: Optional limit on number of results (max 100)
|
43
|
+
order: Optional sort order ("asc" or "desc")
|
44
|
+
status_code: Optional filter by status code
|
45
|
+
status_class: Optional filter by status_class
|
46
|
+
automation_id: Optional filter by deployment ID
|
47
|
+
webhook_url: Optional filter by webhook URL
|
48
|
+
schema_id: Optional filter by schema ID
|
49
|
+
schema_data_id: Optional filter by schema data ID
|
50
|
+
|
51
|
+
Returns:
|
52
|
+
PreparedRequest: The prepared request
|
53
|
+
"""
|
54
|
+
params = {
|
55
|
+
"before": before,
|
56
|
+
"after": after,
|
57
|
+
"limit": limit,
|
58
|
+
"order": order,
|
59
|
+
"status_code": status_code,
|
60
|
+
"status_class": status_class,
|
61
|
+
"automation_id": automation_id,
|
62
|
+
"webhook_url": webhook_url,
|
63
|
+
"schema_id": schema_id,
|
64
|
+
"schema_data_id": schema_data_id,
|
65
|
+
}
|
66
|
+
# Remove None values
|
67
|
+
params = {k: v for k, v in params.items() if v is not None}
|
68
|
+
|
69
|
+
return PreparedRequest(method="GET", url=f"/v1/processors/{processor_id}/automations/logs", params=params)
|
70
|
+
|
71
|
+
def prepare_rerun(self, processor_id: str, log_id: str) -> PreparedRequest:
|
72
|
+
"""Rerun a webhook from an existing AutomationLog.
|
73
|
+
|
74
|
+
Args:
|
75
|
+
processor_id: ID of the processor
|
76
|
+
log_id: ID of the log to rerun
|
77
|
+
|
78
|
+
Returns:
|
79
|
+
PreparedRequest: The prepared request
|
80
|
+
"""
|
81
|
+
return PreparedRequest(method="POST", url=f"/v1/processors/{processor_id}/automations/logs/{log_id}/rerun")
|
82
|
+
|
83
|
+
|
84
|
+
class Logs(SyncAPIResource, LogsMixin):
|
85
|
+
"""Logs API wrapper for managing automation logs"""
|
86
|
+
|
87
|
+
def get(self, processor_id: str, log_id: str) -> AutomationLog:
|
88
|
+
"""Get a specific automation log by ID.
|
89
|
+
|
90
|
+
Args:
|
91
|
+
processor_id: ID of the processor
|
92
|
+
log_id: ID of the log to retrieve
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
AutomationLog: The automation log
|
96
|
+
"""
|
97
|
+
request = self.prepare_get(processor_id, log_id)
|
98
|
+
response = self._client._prepared_request(request)
|
99
|
+
return AutomationLog.model_validate(response)
|
100
|
+
|
101
|
+
def list(
|
102
|
+
self,
|
103
|
+
processor_id: str,
|
104
|
+
before: Optional[str] = None,
|
105
|
+
after: Optional[str] = None,
|
106
|
+
limit: Optional[int] = 10,
|
107
|
+
order: Optional[Literal["asc", "desc"]] = "desc",
|
108
|
+
status_code: Optional[int] = None,
|
109
|
+
status_class: Optional[Literal["2xx", "3xx", "4xx", "5xx"]] = None,
|
110
|
+
automation_id: Optional[str] = None,
|
111
|
+
webhook_url: Optional[str] = None,
|
112
|
+
schema_id: Optional[str] = None,
|
113
|
+
schema_data_id: Optional[str] = None,
|
114
|
+
) -> ListLogs:
|
115
|
+
"""List automation logs with pagination support.
|
116
|
+
|
117
|
+
Args:
|
118
|
+
processor_id: ID of the processor
|
119
|
+
before: Optional cursor for pagination before a specific log ID
|
120
|
+
after: Optional cursor for pagination after a specific log ID
|
121
|
+
limit: Optional limit on number of results (max 100)
|
122
|
+
order: Optional sort order ("asc" or "desc")
|
123
|
+
status_code: Optional filter by status code
|
124
|
+
status_class: Optional filter by status_class
|
125
|
+
automation_id: Optional filter by deployment ID
|
126
|
+
webhook_url: Optional filter by webhook URL
|
127
|
+
schema_id: Optional filter by schema ID
|
128
|
+
schema_data_id: Optional filter by schema data ID
|
129
|
+
|
130
|
+
Returns:
|
131
|
+
ListLogs: Paginated list of automation logs with metadata
|
132
|
+
"""
|
133
|
+
request = self.prepare_list(processor_id, before, after, limit, order, status_code, status_class, automation_id, webhook_url, schema_id, schema_data_id)
|
134
|
+
response = self._client._prepared_request(request)
|
135
|
+
return ListLogs.model_validate(response)
|
136
|
+
|
137
|
+
def rerun(self, processor_id: str, log_id: str) -> ExternalRequestLog:
|
138
|
+
"""Rerun a webhook from an existing AutomationLog.
|
139
|
+
|
140
|
+
Args:
|
141
|
+
processor_id: ID of the processor
|
142
|
+
log_id: ID of the log to rerun
|
143
|
+
|
144
|
+
Returns:
|
145
|
+
ExternalRequestLog: The result of the rerun webhook call
|
146
|
+
"""
|
147
|
+
request = self.prepare_rerun(processor_id, log_id)
|
148
|
+
response = self._client._prepared_request(request)
|
149
|
+
|
150
|
+
print(f"Webhook call run successfully. Log available at https://www.retab.com/dashboard/processors/{processor_id}/logs/{log_id}")
|
151
|
+
|
152
|
+
return ExternalRequestLog.model_validate(response)
|
153
|
+
|
154
|
+
|
155
|
+
class AsyncLogs(AsyncAPIResource, LogsMixin):
|
156
|
+
"""Async Logs API wrapper for managing automation logs"""
|
157
|
+
|
158
|
+
async def get(self, processor_id: str, log_id: str) -> AutomationLog:
|
159
|
+
"""Get a specific automation log by ID.
|
160
|
+
|
161
|
+
Args:
|
162
|
+
processor_id: ID of the processor
|
163
|
+
log_id: ID of the log to retrieve
|
164
|
+
|
165
|
+
Returns:
|
166
|
+
AutomationLog: The automation log
|
167
|
+
"""
|
168
|
+
request = self.prepare_get(processor_id, log_id)
|
169
|
+
response = await self._client._prepared_request(request)
|
170
|
+
return AutomationLog.model_validate(response)
|
171
|
+
|
172
|
+
async def list(
|
173
|
+
self,
|
174
|
+
processor_id: str,
|
175
|
+
before: Optional[str] = None,
|
176
|
+
after: Optional[str] = None,
|
177
|
+
limit: Optional[int] = 10,
|
178
|
+
order: Optional[Literal["asc", "desc"]] = "desc",
|
179
|
+
status_code: Optional[int] = None,
|
180
|
+
status_class: Optional[Literal["2xx", "3xx", "4xx", "5xx"]] = None,
|
181
|
+
automation_id: Optional[str] = None,
|
182
|
+
webhook_url: Optional[str] = None,
|
183
|
+
schema_id: Optional[str] = None,
|
184
|
+
schema_data_id: Optional[str] = None,
|
185
|
+
) -> ListLogs:
|
186
|
+
"""List automation logs with pagination support.
|
187
|
+
|
188
|
+
Args:
|
189
|
+
before: Optional cursor for pagination before a specific log ID
|
190
|
+
after: Optional cursor for pagination after a specific log ID
|
191
|
+
limit: Optional limit on number of results (max 100)
|
192
|
+
order: Optional sort order ("asc" or "desc")
|
193
|
+
status_code: Optional filter by status code
|
194
|
+
status_class: Optional filter by status_class
|
195
|
+
automation_id: Optional filter by deployment ID
|
196
|
+
webhook_url: Optional filter by webhook URL
|
197
|
+
schema_id: Optional filter by schema ID
|
198
|
+
schema_data_id: Optional filter by schema data ID
|
199
|
+
|
200
|
+
Returns:
|
201
|
+
ListLogs: Paginated list of automation logs with metadata
|
202
|
+
"""
|
203
|
+
request = self.prepare_list(processor_id, before, after, limit, order, status_code, status_class, automation_id, webhook_url, schema_id, schema_data_id)
|
204
|
+
response = await self._client._prepared_request(request)
|
205
|
+
return ListLogs.model_validate(response)
|
206
|
+
|
207
|
+
async def rerun(self, processor_id: str, log_id: str) -> ExternalRequestLog:
|
208
|
+
"""Rerun a webhook from an existing AutomationLog.
|
209
|
+
|
210
|
+
Args:
|
211
|
+
processor_id: ID of the processor
|
212
|
+
log_id: ID of the log to rerun
|
213
|
+
|
214
|
+
Returns:
|
215
|
+
ExternalRequestLog: The result of the rerun webhook call
|
216
|
+
"""
|
217
|
+
request = self.prepare_rerun(processor_id, log_id)
|
218
|
+
response = await self._client._prepared_request(request)
|
219
|
+
|
220
|
+
print(f"Webhook call run successfully. Log available at https://www.retab.com/dashboard/processors/{processor_id}/logs/{log_id}")
|
221
|
+
|
222
|
+
return ExternalRequestLog.model_validate(response)
|
@@ -0,0 +1,423 @@
|
|
1
|
+
from io import IOBase
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import Any, List, Literal, Optional
|
4
|
+
|
5
|
+
from pydantic import EmailStr, HttpUrl
|
6
|
+
from ....types.standards import FieldUnset
|
7
|
+
|
8
|
+
from ...._resource import AsyncAPIResource, SyncAPIResource
|
9
|
+
from ....utils.mime import prepare_mime_document
|
10
|
+
from ....types.automations.mailboxes import ListMailboxes, Mailbox, UpdateMailboxRequest
|
11
|
+
from ....types.mime import EmailData, MIMEData
|
12
|
+
from ....types.standards import PreparedRequest
|
13
|
+
|
14
|
+
|
15
|
+
class MailBoxesMixin:
|
16
|
+
mailboxes_base_url: str = "/v1/processors/automations/mailboxes"
|
17
|
+
|
18
|
+
def prepare_create(
|
19
|
+
self,
|
20
|
+
email: str,
|
21
|
+
name: str,
|
22
|
+
processor_id: str,
|
23
|
+
webhook_url: str,
|
24
|
+
authorized_domains: list[str] = FieldUnset,
|
25
|
+
authorized_emails: list[EmailStr] = FieldUnset,
|
26
|
+
webhook_headers: dict[str, str] = FieldUnset,
|
27
|
+
default_language: str = FieldUnset,
|
28
|
+
need_validation: bool = FieldUnset,
|
29
|
+
) -> PreparedRequest:
|
30
|
+
"""Create a new email automation configuration."""
|
31
|
+
mailbox_dict: dict[str, Any] = {
|
32
|
+
'name': name,
|
33
|
+
'processor_id': processor_id,
|
34
|
+
'webhook_url': webhook_url,
|
35
|
+
'email': email,
|
36
|
+
}
|
37
|
+
if default_language is not FieldUnset:
|
38
|
+
mailbox_dict['default_language'] = default_language
|
39
|
+
if webhook_headers is not FieldUnset:
|
40
|
+
mailbox_dict['webhook_headers'] = webhook_headers
|
41
|
+
if need_validation is not FieldUnset:
|
42
|
+
mailbox_dict['need_validation'] = need_validation
|
43
|
+
if authorized_domains is not FieldUnset:
|
44
|
+
mailbox_dict['authorized_domains'] = authorized_domains
|
45
|
+
if authorized_emails is not FieldUnset:
|
46
|
+
mailbox_dict['authorized_emails'] = authorized_emails
|
47
|
+
|
48
|
+
mailbox = Mailbox(**mailbox_dict)
|
49
|
+
return PreparedRequest(method="POST", url=self.mailboxes_base_url, data=mailbox.model_dump(mode="json", exclude_unset=True))
|
50
|
+
|
51
|
+
def prepare_list(
|
52
|
+
self,
|
53
|
+
processor_id: str,
|
54
|
+
before: str | None = None,
|
55
|
+
after: str | None = None,
|
56
|
+
limit: int = 10,
|
57
|
+
order: Literal["asc", "desc"] | None = "desc",
|
58
|
+
email: Optional[str] = None,
|
59
|
+
name: Optional[str] = None,
|
60
|
+
webhook_url: Optional[str] = None,
|
61
|
+
) -> PreparedRequest:
|
62
|
+
params = {
|
63
|
+
"processor_id": processor_id,
|
64
|
+
"before": before,
|
65
|
+
"after": after,
|
66
|
+
"limit": limit,
|
67
|
+
"order": order,
|
68
|
+
"email": email,
|
69
|
+
"name": name,
|
70
|
+
"webhook_url": webhook_url,
|
71
|
+
}
|
72
|
+
# Remove None values
|
73
|
+
params = {k: v for k, v in params.items() if v is not None}
|
74
|
+
|
75
|
+
return PreparedRequest(method="GET", url=self.mailboxes_base_url, params=params)
|
76
|
+
|
77
|
+
def prepare_get(self, mailbox_id: str) -> PreparedRequest:
|
78
|
+
return PreparedRequest(method="GET", url=f"{self.mailboxes_base_url}/{mailbox_id}")
|
79
|
+
|
80
|
+
def prepare_update(
|
81
|
+
self,
|
82
|
+
mailbox_id: str,
|
83
|
+
name: str = FieldUnset,
|
84
|
+
default_language: str = FieldUnset,
|
85
|
+
webhook_url: str = FieldUnset,
|
86
|
+
webhook_headers: dict[str, str] = FieldUnset,
|
87
|
+
need_validation: bool = FieldUnset,
|
88
|
+
authorized_domains: list[str] = FieldUnset,
|
89
|
+
authorized_emails: list[str] = FieldUnset,
|
90
|
+
) -> PreparedRequest:
|
91
|
+
update_dict: dict[str, Any] = {}
|
92
|
+
if name is not FieldUnset:
|
93
|
+
update_dict['name'] = name
|
94
|
+
if default_language is not FieldUnset:
|
95
|
+
update_dict['default_language'] = default_language
|
96
|
+
if webhook_url is not FieldUnset:
|
97
|
+
update_dict['webhook_url'] = webhook_url
|
98
|
+
if webhook_headers is not FieldUnset:
|
99
|
+
update_dict['webhook_headers'] = webhook_headers
|
100
|
+
if need_validation is not FieldUnset:
|
101
|
+
update_dict['need_validation'] = need_validation
|
102
|
+
if authorized_domains is not FieldUnset:
|
103
|
+
update_dict['authorized_domains'] = authorized_domains
|
104
|
+
if authorized_emails is not FieldUnset:
|
105
|
+
update_dict['authorized_emails'] = authorized_emails
|
106
|
+
|
107
|
+
update_mailbox_request = UpdateMailboxRequest(**update_dict)
|
108
|
+
return PreparedRequest(method="PUT", url=f"/v1/processors/automations/mailboxes/{mailbox_id}", data=update_mailbox_request.model_dump(mode="json", exclude_unset=True))
|
109
|
+
|
110
|
+
def prepare_delete(self, mailbox_id: str) -> PreparedRequest:
|
111
|
+
return PreparedRequest(method="DELETE", url=f"/v1/processors/automations/mailboxes/{mailbox_id}", raise_for_status=True)
|
112
|
+
|
113
|
+
|
114
|
+
class Mailboxes(SyncAPIResource, MailBoxesMixin):
|
115
|
+
"""Emails API wrapper for managing email automation configurations"""
|
116
|
+
|
117
|
+
def __init__(self, client: Any) -> None:
|
118
|
+
super().__init__(client=client)
|
119
|
+
self.tests = TestMailboxes(client=client)
|
120
|
+
|
121
|
+
def create(
|
122
|
+
self,
|
123
|
+
email: str,
|
124
|
+
name: str,
|
125
|
+
webhook_url: str,
|
126
|
+
processor_id: str,
|
127
|
+
authorized_domains: list[str] = FieldUnset,
|
128
|
+
authorized_emails: list[EmailStr] = FieldUnset,
|
129
|
+
webhook_headers: dict[str, str] = FieldUnset,
|
130
|
+
default_language: str = FieldUnset,
|
131
|
+
need_validation: bool = FieldUnset,
|
132
|
+
) -> Mailbox:
|
133
|
+
"""Create a new email automation configuration.
|
134
|
+
|
135
|
+
Args:
|
136
|
+
email: Email address for the mailbox
|
137
|
+
name: Name of the mailbox
|
138
|
+
webhook_url: Webhook URL to receive processed emails
|
139
|
+
processor_id: ID of the processor to use for the mailbox
|
140
|
+
authorized_domains: List of authorized domains for the mailbox
|
141
|
+
authorized_emails: List of authorized emails for the mailbox
|
142
|
+
webhook_headers: Webhook headers to send with processed emails
|
143
|
+
|
144
|
+
Returns:
|
145
|
+
Mailbox: The created mailbox configuration
|
146
|
+
"""
|
147
|
+
|
148
|
+
request = self.prepare_create(
|
149
|
+
email=email,
|
150
|
+
name=name,
|
151
|
+
processor_id=processor_id,
|
152
|
+
webhook_url=webhook_url,
|
153
|
+
authorized_domains=authorized_domains,
|
154
|
+
authorized_emails=authorized_emails,
|
155
|
+
webhook_headers=webhook_headers,
|
156
|
+
default_language=default_language,
|
157
|
+
need_validation=need_validation,
|
158
|
+
)
|
159
|
+
response = self._client._prepared_request(request)
|
160
|
+
|
161
|
+
print(f"Mailbox {response['email']} created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
|
162
|
+
|
163
|
+
return Mailbox.model_validate(response)
|
164
|
+
|
165
|
+
def list(
|
166
|
+
self,
|
167
|
+
processor_id: str,
|
168
|
+
before: str | None = None,
|
169
|
+
after: str | None = None,
|
170
|
+
limit: int = 10,
|
171
|
+
order: Literal["asc", "desc"] | None = "desc",
|
172
|
+
name: Optional[str] = None,
|
173
|
+
email: Optional[str] = None,
|
174
|
+
webhook_url: Optional[str] = None,
|
175
|
+
) -> ListMailboxes:
|
176
|
+
"""List all email automation configurations.
|
177
|
+
|
178
|
+
Args:
|
179
|
+
before: Optional cursor for pagination - get results before this log ID
|
180
|
+
after: Optional cursor for pagination - get results after this log ID
|
181
|
+
limit: Maximum number of logs to return (1-100, default 10)
|
182
|
+
order: Sort order by creation time - "asc" or "desc" (default "desc")
|
183
|
+
email: Optional email address filter
|
184
|
+
webhook_url: Optional webhook URL filter
|
185
|
+
schema_id: Optional schema ID filter
|
186
|
+
schema_data_id: Optional schema data ID filter
|
187
|
+
|
188
|
+
Returns:
|
189
|
+
ListMailboxes: List of mailbox configurations
|
190
|
+
"""
|
191
|
+
request = self.prepare_list(
|
192
|
+
processor_id=processor_id,
|
193
|
+
before=before,
|
194
|
+
after=after,
|
195
|
+
limit=limit,
|
196
|
+
order=order,
|
197
|
+
email=email,
|
198
|
+
name=name,
|
199
|
+
webhook_url=webhook_url,
|
200
|
+
)
|
201
|
+
response = self._client._prepared_request(request)
|
202
|
+
return ListMailboxes.model_validate(response)
|
203
|
+
|
204
|
+
def get(self, mailbox_id: str) -> Mailbox:
|
205
|
+
"""Get a specific email automation configuration.
|
206
|
+
|
207
|
+
Args:
|
208
|
+
mailbox_id: ID of the mailbox
|
209
|
+
|
210
|
+
Returns:
|
211
|
+
Mailbox: The mailbox configuration
|
212
|
+
"""
|
213
|
+
request = self.prepare_get(mailbox_id)
|
214
|
+
response = self._client._prepared_request(request)
|
215
|
+
return Mailbox.model_validate(response)
|
216
|
+
|
217
|
+
def update(
|
218
|
+
self,
|
219
|
+
mailbox_id: str,
|
220
|
+
name: str = FieldUnset,
|
221
|
+
default_language: str = FieldUnset,
|
222
|
+
webhook_url: str = FieldUnset,
|
223
|
+
webhook_headers: dict[str, str] = FieldUnset,
|
224
|
+
need_validation: bool = FieldUnset,
|
225
|
+
authorized_domains: List[str] = FieldUnset,
|
226
|
+
authorized_emails: List[str] = FieldUnset,
|
227
|
+
) -> Mailbox:
|
228
|
+
"""Update an email automation configuration.
|
229
|
+
|
230
|
+
Args:
|
231
|
+
email: Email address of the mailbox to update
|
232
|
+
name: New name
|
233
|
+
default_language: New default language
|
234
|
+
webhook_url: New webhook configuration
|
235
|
+
webhook_headers: New webhook configuration
|
236
|
+
need_validation: New webhook configuration
|
237
|
+
authorized_domains: New webhook configuration
|
238
|
+
authorized_emails: New webhook configuration
|
239
|
+
|
240
|
+
Returns:
|
241
|
+
Mailbox: The updated mailbox configuration
|
242
|
+
"""
|
243
|
+
request = self.prepare_update(
|
244
|
+
mailbox_id=mailbox_id,
|
245
|
+
name=name,
|
246
|
+
default_language=default_language,
|
247
|
+
webhook_url=webhook_url,
|
248
|
+
webhook_headers=webhook_headers,
|
249
|
+
need_validation=need_validation,
|
250
|
+
authorized_domains=authorized_domains,
|
251
|
+
authorized_emails=authorized_emails,
|
252
|
+
)
|
253
|
+
response = self._client._prepared_request(request)
|
254
|
+
return Mailbox.model_validate(response)
|
255
|
+
|
256
|
+
def delete(self, mailbox_id: str) -> None:
|
257
|
+
"""Delete an email automation configuration.
|
258
|
+
|
259
|
+
Args:
|
260
|
+
email: Email address of the mailbox to delete
|
261
|
+
"""
|
262
|
+
request = self.prepare_delete(mailbox_id)
|
263
|
+
self._client._prepared_request(request)
|
264
|
+
return None
|
265
|
+
|
266
|
+
|
267
|
+
class AsyncMailboxes(AsyncAPIResource, MailBoxesMixin):
|
268
|
+
def __init__(self, client: Any) -> None:
|
269
|
+
super().__init__(client=client)
|
270
|
+
self.tests = AsyncTestMailboxes(client=client)
|
271
|
+
|
272
|
+
async def create(
|
273
|
+
self,
|
274
|
+
email: str,
|
275
|
+
name: str,
|
276
|
+
webhook_url: str,
|
277
|
+
processor_id: str,
|
278
|
+
authorized_domains: List[str] = FieldUnset,
|
279
|
+
authorized_emails: List[EmailStr] = FieldUnset,
|
280
|
+
webhook_headers: dict[str, str] = FieldUnset,
|
281
|
+
default_language: str = FieldUnset,
|
282
|
+
need_validation: bool = FieldUnset,
|
283
|
+
) -> Mailbox:
|
284
|
+
request = self.prepare_create(
|
285
|
+
email=email,
|
286
|
+
name=name,
|
287
|
+
processor_id=processor_id,
|
288
|
+
webhook_url=webhook_url,
|
289
|
+
authorized_domains=authorized_domains,
|
290
|
+
authorized_emails=authorized_emails,
|
291
|
+
webhook_headers=webhook_headers,
|
292
|
+
default_language=default_language,
|
293
|
+
need_validation=need_validation,
|
294
|
+
)
|
295
|
+
response = await self._client._prepared_request(request)
|
296
|
+
|
297
|
+
print(f"Mailbox {response['email']} created. Url: https://www.retab.com/dashboard/processors/automations/{response['id']}")
|
298
|
+
|
299
|
+
return Mailbox.model_validate(response)
|
300
|
+
|
301
|
+
async def list(
|
302
|
+
self,
|
303
|
+
processor_id: str,
|
304
|
+
before: str | None = None,
|
305
|
+
after: str | None = None,
|
306
|
+
limit: int = 10,
|
307
|
+
order: Literal["asc", "desc"] | None = "desc",
|
308
|
+
email: str | None = None,
|
309
|
+
name: str | None = None,
|
310
|
+
webhook_url: str | None = None,
|
311
|
+
) -> ListMailboxes:
|
312
|
+
request = self.prepare_list(
|
313
|
+
processor_id=processor_id,
|
314
|
+
before=before,
|
315
|
+
after=after,
|
316
|
+
limit=limit,
|
317
|
+
order=order,
|
318
|
+
email=email,
|
319
|
+
name=name,
|
320
|
+
webhook_url=webhook_url,
|
321
|
+
)
|
322
|
+
response = await self._client._prepared_request(request)
|
323
|
+
return ListMailboxes.model_validate(response)
|
324
|
+
|
325
|
+
async def get(self, mailbox_id: str) -> Mailbox:
|
326
|
+
request = self.prepare_get(mailbox_id)
|
327
|
+
response = await self._client._prepared_request(request)
|
328
|
+
return Mailbox.model_validate(response)
|
329
|
+
|
330
|
+
async def update(
|
331
|
+
self,
|
332
|
+
mailbox_id: str,
|
333
|
+
name: str = FieldUnset,
|
334
|
+
default_language: str = FieldUnset,
|
335
|
+
webhook_url: str = FieldUnset,
|
336
|
+
webhook_headers: dict[str, str] = FieldUnset,
|
337
|
+
need_validation: bool = FieldUnset,
|
338
|
+
authorized_domains: List[str] = FieldUnset,
|
339
|
+
authorized_emails: List[str] = FieldUnset,
|
340
|
+
) -> Mailbox:
|
341
|
+
request = self.prepare_update(
|
342
|
+
mailbox_id=mailbox_id,
|
343
|
+
name=name,
|
344
|
+
default_language=default_language,
|
345
|
+
webhook_url=webhook_url,
|
346
|
+
webhook_headers=webhook_headers,
|
347
|
+
need_validation=need_validation,
|
348
|
+
authorized_domains=authorized_domains,
|
349
|
+
authorized_emails=authorized_emails,
|
350
|
+
)
|
351
|
+
response = await self._client._prepared_request(request)
|
352
|
+
return Mailbox.model_validate(response)
|
353
|
+
|
354
|
+
async def delete(self, mailbox_id: str) -> None:
|
355
|
+
request = self.prepare_delete(mailbox_id)
|
356
|
+
await self._client._prepared_request(request)
|
357
|
+
return None
|
358
|
+
|
359
|
+
|
360
|
+
class TestMailboxesMixin:
|
361
|
+
def prepare_forward(
|
362
|
+
self,
|
363
|
+
mailbox_id: str,
|
364
|
+
document: Path | str | IOBase | HttpUrl | MIMEData,
|
365
|
+
verbose: bool = True,
|
366
|
+
) -> PreparedRequest:
|
367
|
+
mime_document = prepare_mime_document(document)
|
368
|
+
return PreparedRequest(method="POST", url=f"/v1/processors/automations/mailboxes/tests/forward/{mailbox_id}", data={"document": mime_document.model_dump()})
|
369
|
+
|
370
|
+
def print_forward_verbose(self, email_data: EmailData) -> None:
|
371
|
+
print("\nTEST EMAIL FORWARDING RESULTS:")
|
372
|
+
print("\n#########################")
|
373
|
+
print(f"Email ID: {email_data.id}")
|
374
|
+
print(f"Subject: {email_data.subject}")
|
375
|
+
print(f"From: {email_data.sender}")
|
376
|
+
print(f"To: {', '.join(str(r) for r in email_data.recipients_to)}")
|
377
|
+
if email_data.recipients_cc:
|
378
|
+
print(f"CC: {', '.join(str(r) for r in email_data.recipients_cc)}")
|
379
|
+
print(f"Sent at: {email_data.sent_at}")
|
380
|
+
print(f"Attachments: {len(email_data.attachments)}")
|
381
|
+
if email_data.body_plain:
|
382
|
+
print("\nBody Preview:")
|
383
|
+
print(email_data.body_plain[:500] + "..." if len(email_data.body_plain) > 500 else email_data.body_plain)
|
384
|
+
|
385
|
+
|
386
|
+
class TestMailboxes(SyncAPIResource, TestMailboxesMixin):
|
387
|
+
def forward(
|
388
|
+
self,
|
389
|
+
mailbox_id: str,
|
390
|
+
document: Path | str | IOBase | HttpUrl | MIMEData,
|
391
|
+
verbose: bool = True,
|
392
|
+
) -> EmailData:
|
393
|
+
"""Mock endpoint that simulates the complete email forwarding process with sample data.
|
394
|
+
|
395
|
+
Args:
|
396
|
+
email: Email address of the mailbox to mock
|
397
|
+
|
398
|
+
Returns:
|
399
|
+
DocumentExtractResponse: The simulated extraction response
|
400
|
+
"""
|
401
|
+
request = self.prepare_forward(mailbox_id, document, verbose)
|
402
|
+
response = self._client._prepared_request(request)
|
403
|
+
|
404
|
+
email_data = EmailData.model_validate(response)
|
405
|
+
|
406
|
+
if verbose:
|
407
|
+
self.print_forward_verbose(email_data)
|
408
|
+
return email_data
|
409
|
+
|
410
|
+
|
411
|
+
class AsyncTestMailboxes(AsyncAPIResource, TestMailboxesMixin):
|
412
|
+
async def forward(
|
413
|
+
self,
|
414
|
+
mailbox_id: str,
|
415
|
+
document: Path | str | IOBase | HttpUrl | MIMEData,
|
416
|
+
verbose: bool = True,
|
417
|
+
) -> EmailData:
|
418
|
+
request = self.prepare_forward(mailbox_id, document, verbose)
|
419
|
+
response = await self._client._prepared_request(request)
|
420
|
+
email_data = EmailData.model_validate(response)
|
421
|
+
if verbose:
|
422
|
+
self.print_forward_verbose(email_data)
|
423
|
+
return email_data
|