mailbox-org-api 2.2__tar.gz → 2.4__tar.gz

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.
Files changed (21) hide show
  1. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/PKG-INFO +15 -9
  2. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/README.md +13 -7
  3. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/mailbox_org_api/APIClient.py +192 -151
  4. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/mailbox_org_api/APIError.py +2 -1
  5. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/mailbox_org_api/Invoice.py +1 -1
  6. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/mailbox_org_api.egg-info/PKG-INFO +15 -9
  7. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/pyproject.toml +2 -2
  8. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/setup.py +2 -2
  9. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/tests/TestAPIClient.py +39 -11
  10. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/tests/TestAccount.py +3 -2
  11. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/tests/TestInvoice.py +2 -1
  12. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/tests/TestMail.py +3 -1
  13. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/LICENSE +0 -0
  14. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/mailbox_org_api/Account.py +0 -0
  15. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/mailbox_org_api/Mail.py +0 -0
  16. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/mailbox_org_api/__init__.py +0 -0
  17. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/mailbox_org_api.egg-info/SOURCES.txt +0 -0
  18. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/mailbox_org_api.egg-info/dependency_links.txt +0 -0
  19. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/mailbox_org_api.egg-info/top_level.txt +0 -0
  20. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/setup.cfg +0 -0
  21. {mailbox_org_api-2.2 → mailbox_org_api-2.4}/tests/__init__.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mailbox-org-api
3
- Version: 2.2
4
- Summary: A library to access the mailbox.org Business API.
3
+ Version: 2.4
4
+ Summary: A library to access the mailbox Business API.
5
5
  Author: Hendrik Schlange
6
6
  Author-email: Hendrik Schlange <mail@heshsum.de>
7
7
  Project-URL: Homepage, https://github.com/heshsum/mailbox-org-api
@@ -36,11 +36,15 @@ pip install mailbox-org-api
36
36
  pip install git+https://github.com/heshsum/mailbox-org-api
37
37
  ```
38
38
 
39
- ## Usage
39
+ ## Usage and documentation
40
40
  Basic usage is fairly straightforward. The naming scheme of the functions is similar to the naming at mailbox.org,
41
- but instead of points, it uses underscores (e.g. instead of `mail.add` it's `mail_add`).
41
+ but instead of points, it uses underscores (e.g. instead of `mail.add` it's `mail_add`).
42
+
43
+ Therefore, the functions mirror the functions as provided and documented at mailbox:
44
+ [api.mailbox.org](https://api.mailbox.org)
45
+
42
46
  Additionally, some helper functions for common or more complicated tasks are included to make life a bit easier,
43
- e.g. for changing plans, password and to retrieve invoices.
47
+ e.g. for changing plans, password and to retrieving invoices.
44
48
 
45
49
  ```python
46
50
  from mailbox_org_api import APIClient
@@ -87,6 +91,8 @@ api.mail_set_forwards('foo@bar.com', ['forward1@bar.com', 'forward2@bar.com'])
87
91
  api.deauth()
88
92
  ```
89
93
 
94
+ More information can be found in the [Wiki](https://github.com/heshsum/mailbox-org-api/wiki)
95
+
90
96
  ## Common tasks
91
97
  mailbox_org_api includes a number of helper functions to make common tasks simpler. These include:
92
98
 
@@ -163,21 +169,21 @@ Usage:
163
169
  api.account_invoice_get_token('BMBO-1234-24')
164
170
  ```
165
171
 
166
- ### account_invoice_get_pdf
172
+ ### account_invoice_get_file
167
173
  Invoices are provided as Based64 encoded gz Strings. This function
168
174
  1. takes the invoice ID
169
175
  2. retrieves the token for the invoice
170
176
  3. gets the binary data
171
177
  4. decodes the Base64
172
178
  5. decompresses it
173
- 6. returns the bytes of the actual PDF
179
+ 6. returns the bytes of the actual invoice file
174
180
 
175
181
  Usage
176
182
  ```python
177
183
  invoice_id = 'BMBO-1234-24'
178
- account_name = 'some_user'
184
+ account_name = 'foo'
179
185
  with open(invoice_id + '.pdf', 'w') as file:
180
- file.write(api.account_invoice_get_pdf(account_name, invoice_id))
186
+ file.write(api.account_invoice_get_file(account_name, invoice_id, 'PDF'))
181
187
  ```
182
188
 
183
189
  ## Here be dragons
@@ -19,11 +19,15 @@ pip install mailbox-org-api
19
19
  pip install git+https://github.com/heshsum/mailbox-org-api
20
20
  ```
21
21
 
22
- ## Usage
22
+ ## Usage and documentation
23
23
  Basic usage is fairly straightforward. The naming scheme of the functions is similar to the naming at mailbox.org,
24
- but instead of points, it uses underscores (e.g. instead of `mail.add` it's `mail_add`).
24
+ but instead of points, it uses underscores (e.g. instead of `mail.add` it's `mail_add`).
25
+
26
+ Therefore, the functions mirror the functions as provided and documented at mailbox:
27
+ [api.mailbox.org](https://api.mailbox.org)
28
+
25
29
  Additionally, some helper functions for common or more complicated tasks are included to make life a bit easier,
26
- e.g. for changing plans, password and to retrieve invoices.
30
+ e.g. for changing plans, password and to retrieving invoices.
27
31
 
28
32
  ```python
29
33
  from mailbox_org_api import APIClient
@@ -70,6 +74,8 @@ api.mail_set_forwards('foo@bar.com', ['forward1@bar.com', 'forward2@bar.com'])
70
74
  api.deauth()
71
75
  ```
72
76
 
77
+ More information can be found in the [Wiki](https://github.com/heshsum/mailbox-org-api/wiki)
78
+
73
79
  ## Common tasks
74
80
  mailbox_org_api includes a number of helper functions to make common tasks simpler. These include:
75
81
 
@@ -146,21 +152,21 @@ Usage:
146
152
  api.account_invoice_get_token('BMBO-1234-24')
147
153
  ```
148
154
 
149
- ### account_invoice_get_pdf
155
+ ### account_invoice_get_file
150
156
  Invoices are provided as Based64 encoded gz Strings. This function
151
157
  1. takes the invoice ID
152
158
  2. retrieves the token for the invoice
153
159
  3. gets the binary data
154
160
  4. decodes the Base64
155
161
  5. decompresses it
156
- 6. returns the bytes of the actual PDF
162
+ 6. returns the bytes of the actual invoice file
157
163
 
158
164
  Usage
159
165
  ```python
160
166
  invoice_id = 'BMBO-1234-24'
161
- account_name = 'some_user'
167
+ account_name = 'foo'
162
168
  with open(invoice_id + '.pdf', 'w') as file:
163
- file.write(api.account_invoice_get_pdf(account_name, invoice_id))
169
+ file.write(api.account_invoice_get_file(account_name, invoice_id, 'PDF'))
164
170
  ```
165
171
 
166
172
  ## Here be dragons
@@ -2,24 +2,28 @@
2
2
  Module for the mailbox Business API client
3
3
  """
4
4
  import json
5
+ from typing import Any
6
+
5
7
  import requests
6
8
  from requests.adapters import HTTPAdapter
7
- from urllib3.util.retry import Retry
8
9
  from requests.exceptions import RequestException
9
- import typing_extensions
10
+ from urllib3.util.retry import Retry
11
+
10
12
  from mailbox_org_api.APIError import APIError
11
13
  from mailbox_org_api.Account import Account
12
- from mailbox_org_api.Mail import Mail
13
14
  from mailbox_org_api.Invoice import Invoice
15
+ from mailbox_org_api.Mail import Mail
14
16
 
15
17
  headers = {'content-type': 'application/json'}
16
18
 
17
19
  keys_to_string = ['additional_cloud_quota', 'additional_mail_quota']
18
20
 
21
+
19
22
  class APIClient:
20
23
  """
21
24
  Object for API Client
22
25
  """
26
+
23
27
  def __init__(self, debug_output=False, max_retries=5):
24
28
  # URL of the API
25
29
  self.url = "https://api.mailbox.org/v1/"
@@ -62,7 +66,7 @@ class APIClient:
62
66
  self.jsonrpc_id += 1
63
67
  return str(self.jsonrpc_id)
64
68
 
65
- def api_request(self, method: str, params: dict) -> dict:
69
+ def api_request(self, method: str, params: dict) -> dict | Any:
66
70
  """
67
71
  Function to send API calls
68
72
  :param method: the method to call
@@ -125,7 +129,7 @@ class APIClient:
125
129
  :param password: the password
126
130
  :return: the API response for the request
127
131
  """
128
- api_response = self.api_request('auth', {'user':username, 'pass':password})
132
+ api_response = self.api_request('auth', {'user': username, 'pass': password})
129
133
  if api_response['session']:
130
134
  # Level gives information about the calls available
131
135
  self.level = api_response["level"]
@@ -143,7 +147,7 @@ class APIClient:
143
147
  Function to close the current API session
144
148
  :return: True if the API session is closed, False otherwise
145
149
  """
146
- api_response = self.api_request('deauth',{})
150
+ api_response = self.api_request('deauth', {})
147
151
  if api_response:
148
152
  # The auth header is stripped
149
153
  self.session.headers.pop("HPLS-AUTH")
@@ -156,7 +160,7 @@ class APIClient:
156
160
  Function for hello world, just to test the connection
157
161
  :return: The response from the mailbox.org Business API
158
162
  """
159
- return self.api_request('hello.world',{})
163
+ return self.api_request('hello.world', {})
160
164
 
161
165
  def hello_innerworld(self):
162
166
  """
@@ -210,9 +214,9 @@ class APIClient:
210
214
  :param account: the account name to get
211
215
  :return: the response from the mailbox.org Business API
212
216
  """
213
- return self.api_request('account.get', {'account':account})
217
+ return self.api_request('account.get', {'account': account})
214
218
 
215
- def account_get_object(self, account:str) -> Account:
219
+ def account_get_object(self, account: str) -> Account:
216
220
  result = self.api_request('account.get', {'account': account})
217
221
  account_object = Account(account)
218
222
  for k, v in result.items():
@@ -256,7 +260,7 @@ class APIClient:
256
260
  :param account: the account name to delete
257
261
  :return: the response from the mailbox.org Business API
258
262
  """
259
- return self.api_request('account.del', {'account':account})
263
+ return self.api_request('account.del', {'account': account})
260
264
 
261
265
  def account_invoice_list(self, account: str) -> dict:
262
266
  """
@@ -264,7 +268,7 @@ class APIClient:
264
268
  :param account: the account name to list
265
269
  :return: the response from the mailbox.org Business API
266
270
  """
267
- return self.api_request('account.invoice.list', {'account':account})
271
+ return self.api_request('account.invoice.list', {'account': account})
268
272
 
269
273
  def account_invoice_get(self, account: str, token: str) -> dict:
270
274
  """
@@ -273,7 +277,7 @@ class APIClient:
273
277
  :param token: the token for the invoice
274
278
  :return: the response from the mailbox.org Business API - the invoice as a Base64 encoded gzipped string
275
279
  """
276
- return self.api_request('account.invoice.get', {'account':account, 'token':token})
280
+ return self.api_request('account.invoice.get', {'account': account, 'token': token})
277
281
 
278
282
  def account_invoice_get_object(self, account: str, invoice_id: str) -> Invoice:
279
283
  """
@@ -300,7 +304,7 @@ class APIClient:
300
304
  """
301
305
  Function to get a list of all invoice ids for a specific account
302
306
  """
303
- response = self.api_request('account.invoice.list', {'account':account})
307
+ response = self.api_request('account.invoice.list', {'account': account})
304
308
  invoices = []
305
309
 
306
310
  for invoice in response:
@@ -313,7 +317,7 @@ class APIClient:
313
317
  """
314
318
  invoices = self.account_invoice_list(account)
315
319
  open_invoices = []
316
-
320
+
317
321
  for i in invoices:
318
322
  if i['status'] == 'open':
319
323
  open_invoices.append(i)
@@ -332,22 +336,12 @@ class APIClient:
332
336
  return invoice['token']
333
337
  raise ValueError('Invoice not found')
334
338
 
335
- @typing_extensions.deprecated('Use account_invoice_get_file instead')
336
- def account_invoice_get_pdf(self, account: str, invoice_id: str) -> bytes:
337
- """
338
- Function to get a specific invoice as a PDf-file
339
- :param account: the account name
340
- :param invoice_id: the invoice ID
341
- :return: the PDF as bytes
342
- """
343
- return self.account_invoice_get_file(account, invoice_id, 'pdf')
344
-
345
339
  def account_invoice_get_file(self, account: str, invoice_id: str, file_type: str) -> bytes:
346
340
  """
347
341
  Function to get a specific invoice as a PDf-file
348
342
  :param account: the account name
349
343
  :param invoice_id: the invoice ID
350
- :param file_type: The file type to return. Valid: csv, pdf and xml
344
+ :param file_type: The file type to return. Valid: CSV, PDF and XML
351
345
  :return: the file as bytes
352
346
  """
353
347
  if file_type not in ('csv', 'pdf', 'xml'):
@@ -365,17 +359,30 @@ class APIClient:
365
359
  # Take the Base64 encoded data (response['bin']), decode the Base 64, decompress the gz and return the bytes
366
360
  return zlib.decompress(base64.b64decode(response['bin']))
367
361
 
368
- def domain_list(self, account: str, search_filter:str = None) -> dict:
362
+ def domain_list(self, account: str, search_filter: str | None = None) -> dict:
369
363
  """
370
364
  Function to list all domains
371
365
  :param account: the account to list domains for
372
366
  :param search_filter: String for optional search filter
373
367
  :return: the API response
374
368
  """
375
- params = {'account':account}
376
- if filter:
377
- params.update({'filter':search_filter})
378
- return self.api_request('domain.list',params)
369
+ params = {'account': account}
370
+ if isinstance(search_filter, str):
371
+ params.update({'filter': str(search_filter)})
372
+ return self.api_request('domain.list', params)
373
+
374
+ def domain_get_list(self, account: str, search_filter: str | None = None) -> list:
375
+ """
376
+ Function to get a List object with domain names for a given account
377
+ :param account: the account to list domains for
378
+ :param search_filter: String for optional search filter
379
+ :return: a List object containing the domain names
380
+ """
381
+ result = self.domain_list(account, search_filter)
382
+ domains = []
383
+ for i in result:
384
+ domains.append(i['domain'])
385
+ return domains
379
386
 
380
387
  def domain_add(self, account: str, domain: str, password: str, **kwargs) -> dict:
381
388
  """
@@ -387,7 +394,7 @@ class APIClient:
387
394
  See documentation here: https://api.mailbox.org/v1/doc/methods/index.html#domain-add
388
395
  :return: the API response
389
396
  """
390
- params = {'account':account, 'domain':domain, 'password':password}
397
+ params = {'account': account, 'domain': domain, 'password': password}
391
398
  params.update({k: v for k, v in kwargs.items() if v is not None})
392
399
  return self.api_request('domain.add', params)
393
400
 
@@ -397,7 +404,7 @@ class APIClient:
397
404
  :param domain: the domain to get
398
405
  :return: the API response
399
406
  """
400
- return self.api_request('domain.get',{'domain':domain})
407
+ return self.api_request('domain.get', {'domain': domain})
401
408
 
402
409
  def domain_capabilities_set(self, domain: str, capabilities: list) -> dict:
403
410
  """
@@ -442,7 +449,7 @@ class APIClient:
442
449
  :param domain: the domain to delete
443
450
  :return: the API response
444
451
  """
445
- return self.api_request('domain.del', {'account':account, 'domain':domain})
452
+ return self.api_request('domain.del', {'account': account, 'domain': domain})
446
453
 
447
454
  def domain_validate_spf(self, domain: str) -> dict:
448
455
  """
@@ -450,10 +457,10 @@ class APIClient:
450
457
  :param domain: the domain to validate
451
458
  :return: the API response - information about the SPF config
452
459
  """
453
- return self.api_request('domain.validate.spf', {'domain':domain})
460
+ return self.api_request('domain.validate.spf', {'domain': domain})
454
461
 
455
- def mail_list(self, domain: str, details: bool = False, page_size: int = None, page: int = None, sort_field: str = None,
456
- sort_order: str = None) -> dict:
462
+ def mail_list(self, domain: str, details: bool = False, page_size: int | None = None, page: int | None = None,
463
+ sort_field: str | None = None, sort_order: str | None = None) -> dict:
457
464
  """
458
465
  Function to list all mailboxes
459
466
  :param domain: the domain to list
@@ -464,8 +471,8 @@ class APIClient:
464
471
  :param sort_order: the order to sort by. Possible values: 'asc', 'desc'
465
472
  :return: the response from the mailbox.org Business API
466
473
  """
467
- args = {'domain':domain, 'details':details, 'page_size':page_size, 'page':page, 'sort_field':sort_field,
468
- 'sort_order':sort_order}
474
+ args = {'domain': domain, 'details': details, 'page_size': page_size, 'page': page, 'sort_field': sort_field,
475
+ 'sort_order': sort_order}
469
476
 
470
477
  # Allowed sort fields as documented here: https://api.mailbox.org/v1/doc/methods/index.html#mail-list
471
478
  mail_list_sort_field = ['mail', 'first_name', 'last_name', 'status', 'domain', 'plan', 'type', 'creation_date']
@@ -487,8 +494,20 @@ class APIClient:
487
494
 
488
495
  return self.api_request('mail.list', params)
489
496
 
490
- def mail_add(self, mail:str, password: str, plan: str, first_name: str, last_name: str, inboxsave: bool = True,
491
- forwards: list = None, **kwargs) -> dict:
497
+ def mail_get_list(self, domain: str) -> list:
498
+ """
499
+ Function to get a list of all mailboxes of a domain as a List object.
500
+ :param domain: the domain to list all mailboxes for.
501
+ :return: a List object containing all mail addresses of the given domain.
502
+ """
503
+ result = self.mail_list(domain)
504
+ mails = []
505
+ for i in result:
506
+ mails.append(i['mail'])
507
+ return mails
508
+
509
+ def mail_add(self, mail: str, password: str, plan: str, first_name: str, last_name: str, inboxsave: bool = True,
510
+ forwards: list | None = None, **kwargs) -> dict:
492
511
  """
493
512
  Function to add a mail
494
513
  :param mail: the mail to add
@@ -507,10 +526,10 @@ class APIClient:
507
526
  'create_own_context': bool, 'title': str, 'birthday': str, 'position': str,
508
527
  'department': str, 'company': str, 'street': str, 'postal_code': str, 'city': str,
509
528
  'phone': str, 'fax': str, 'cell_phone': str, 'recover': bool, 'skip_welcome_mail': bool,
510
- 'uid_extern': str, 'language': str, 'evac_force_activation':bool}
529
+ 'uid_extern': str, 'language': str, 'evac_force_activation': bool}
511
530
 
512
531
  if password and 'password_hash' in kwargs:
513
- raise KeyError('''Simultaneous usage of 'password' and 'password_hash' not allowed.
532
+ raise KeyError('''Simultaneous usage of 'password' and 'password_hash' not allowed.
514
533
  Use 'password' = None if password_hash is used.''')
515
534
 
516
535
  if forwards is None:
@@ -523,8 +542,8 @@ class APIClient:
523
542
  kwargs[k] = str(kwargs[k])
524
543
 
525
544
  # After validation, build parameter list from mail and kwargs
526
- params = {'mail':mail, 'password':password, 'plan':plan, 'first_name':first_name, 'last_name':last_name,
527
- 'inboxsave':inboxsave, 'forwards':forwards}
545
+ params = {'mail': mail, 'password': password, 'plan': plan, 'first_name': first_name, 'last_name': last_name,
546
+ 'inboxsave': inboxsave, 'forwards': forwards}
528
547
  params.update({k: v for k, v in kwargs.items() if v is not None})
529
548
  return self.api_request('mail.add', params)
530
549
 
@@ -535,10 +554,10 @@ class APIClient:
535
554
  :param include_quota_usage: True if the quota usage should be included in the request
536
555
  :return the response for the request
537
556
  """
538
- return self.api_request('mail.get', {'mail':mail, 'include_quota_usage':include_quota_usage})
557
+ return self.api_request('mail.get', {'mail': mail, 'include_quota_usage': include_quota_usage})
539
558
 
540
- def mail_get_object(self, mail:str) -> Mail:
541
- result = self.api_request('mail.get', {'mail':mail, 'include_quota_usage':False})
559
+ def mail_get_object(self, mail: str) -> Mail:
560
+ result = self.api_request('mail.get', {'mail': mail, 'include_quota_usage': False})
542
561
  mail_object = Mail(mail)
543
562
  for k, v in result.items():
544
563
  if v is not None:
@@ -555,15 +574,15 @@ class APIClient:
555
574
  """
556
575
  # Allowed attributes as documented here: https://api.mailbox.org/v1/doc/methods/index.html#mail-set
557
576
  allowed_parameters = {'password': str, 'password_hash': str, 'same_password_allowed': bool,
558
- 'require_reset_password': bool, 'plan': str, 'additional_mail_quota': int,
559
- 'additional_cloud_quota': int, 'first_name': str, 'last_name': str, 'inboxsave': bool,
560
- 'forwards': list, 'aliases': list, 'alternate_mail': str, 'memo': str, 'allow_nets': str,
561
- 'active': bool, 'title': str, 'birthday': str, 'position': str, 'department': str,
562
- 'company': str, 'street': str, 'postal_code': str, 'city': str, 'phone': str, 'fax': str,
563
- 'cell_phone': str, 'uid_extern': str, 'language': str, 'deletion_date': str}
577
+ 'require_reset_password': bool, 'plan': str, 'additional_mail_quota': int,
578
+ 'additional_cloud_quota': int, 'first_name': str, 'last_name': str, 'inboxsave': bool,
579
+ 'forwards': list, 'aliases': list, 'alternate_mail': str, 'memo': str, 'allow_nets': str,
580
+ 'active': bool, 'title': str, 'birthday': str, 'position': str, 'department': str,
581
+ 'company': str, 'street': str, 'postal_code': str, 'city': str, 'phone': str, 'fax': str,
582
+ 'cell_phone': str, 'uid_extern': str, 'language': str, 'deletion_date': str}
564
583
 
565
584
  if 'password' in kwargs and 'password_hash' in kwargs:
566
- raise KeyError('''Simultaneous usage of 'password' and 'password_hash' not allowed.''')
585
+ raise KeyError('''Simultaneous usage of 'password' and 'password_hash' not allowed.''')
567
586
 
568
587
  if 'additional_mail_quota' in kwargs or 'additional_cloud_quota' in kwargs and 'plan' not in kwargs:
569
588
  raise KeyError('''If setting additional quota, 'plan' must be given.''')
@@ -578,9 +597,9 @@ class APIClient:
578
597
  kwargs[k] = str(kwargs[k])
579
598
 
580
599
  # After validation, build parameter list from mail and kwargs
581
- params = {'mail':mail}
600
+ params = {'mail': mail}
582
601
  params.update({k: v for k, v in kwargs.items() if v is not None})
583
-
602
+
584
603
  return self.api_request('mail.set', params)
585
604
 
586
605
  def mail_set_password(self, mail: str, password: str) -> dict:
@@ -590,7 +609,7 @@ class APIClient:
590
609
  :param password: the password to set
591
610
  :return: the response for the request
592
611
  """
593
- return self.api_request('mail.set', {'mail':mail, 'password':password})
612
+ return self.api_request('mail.set', {'mail': mail, 'password': password})
594
613
 
595
614
  def mail_set_password_require_reset(self, mail: str, password: str) -> dict:
596
615
  """
@@ -608,7 +627,7 @@ class APIClient:
608
627
  :param plan: the plan to set
609
628
  :return: the response for the request
610
629
  """
611
- return self.api_request('mail.set', {'mail':mail, 'plan':plan})
630
+ return self.api_request('mail.set', {'mail': mail, 'plan': plan})
612
631
 
613
632
  def mail_set_forwards(self, mail: str, forwards: list) -> dict:
614
633
  """
@@ -617,7 +636,7 @@ class APIClient:
617
636
  :param forwards: a list of addresses to forwards mails to
618
637
  :return: the response for the request
619
638
  """
620
- return self.api_request('mail.set', {'mail':mail, 'forwards':forwards})
639
+ return self.api_request('mail.set', {'mail': mail, 'forwards': forwards})
621
640
 
622
641
  def mail_set_aliases(self, mail: str, aliases: list) -> dict:
623
642
  """
@@ -626,7 +645,7 @@ class APIClient:
626
645
  :param aliases: a list of aliases to set
627
646
  :return: the response for the request
628
647
  """
629
- return self.api_request('mail.set', {'mail':mail, 'aliases':aliases})
648
+ return self.api_request('mail.set', {'mail': mail, 'aliases': aliases})
630
649
 
631
650
  def mail_set_state(self, mail: str, active: bool) -> dict:
632
651
  """
@@ -635,7 +654,7 @@ class APIClient:
635
654
  :param active: True if the mail should be active, False if it shall be deactivated
636
655
  :return: the response for the request
637
656
  """
638
- return self.api_request('mail.set', {'mail':mail, 'active':active})
657
+ return self.api_request('mail.set', {'mail': mail, 'active': active})
639
658
 
640
659
  def mail_set_additional_mail_quota(self, mail: str, quota: int) -> dict:
641
660
  """
@@ -645,7 +664,7 @@ class APIClient:
645
664
  :return: the response for the request
646
665
  """
647
666
  plan = self.mail_get(mail)['plan']
648
- return self.api_request('mail.set', {'mail': mail, 'plan':plan, 'additional_mail_quota':quota})
667
+ return self.api_request('mail.set', {'mail': mail, 'plan': plan, 'additional_mail_quota': quota})
649
668
 
650
669
  def mail_set_additional_cloud_quota(self, mail: str, quota: int) -> dict:
651
670
  """
@@ -667,7 +686,7 @@ class APIClient:
667
686
  :return: the response for the request
668
687
  """
669
688
  return self.api_request('mail.set', {'mail': mail, 'deletion_date': deletion_date,
670
- 'active': False})
689
+ 'active': False})
671
690
 
672
691
  def mail_capabilities_set(self, mail: str, capabilities: list) -> dict:
673
692
  """
@@ -684,7 +703,7 @@ class APIClient:
684
703
  invalid = set(capabilities) - set(mail_capabilities)
685
704
  if invalid:
686
705
  raise ValueError(f'Invalid capabilities found: {", ".join(invalid)}')
687
- params = {'mail':mail, 'capabilities':list(capabilities)}
706
+ params = {'mail': mail, 'capabilities': list(capabilities)}
688
707
  return self.api_request('mail.capabilities.set', params)
689
708
 
690
709
  def mail_del(self, mail: str) -> dict:
@@ -693,17 +712,17 @@ class APIClient:
693
712
  :param mail: the mail to delete
694
713
  :return: the response for the request
695
714
  """
696
- return self.api_request('mail.del', {'mail':mail})
715
+ return self.api_request('mail.del', {'mail': mail})
697
716
 
698
- def mail_apppassword_list(self, mail:str) -> dict:
717
+ def mail_apppassword_list(self, mail: str) -> dict:
699
718
  """
700
719
  Function to list all app passwords of a given mail
701
720
  :param mail: the mail to list app passwords for
702
721
  :return: the response for the request
703
722
  """
704
- return self.api_request('mail.apppassword.list', {'mail':mail})
723
+ return self.api_request('mail.apppassword.list', {'mail': mail})
705
724
 
706
- def mail_apppassword_add(self, mail:str, memo:str, imap_allowed:bool = True, smtp_allowed:bool = True) -> dict:
725
+ def mail_apppassword_add(self, mail: str, memo: str, imap_allowed: bool = True, smtp_allowed: bool = True) -> dict:
707
726
  """
708
727
  Function to generate a new mail app password for a mail
709
728
  :param mail: the mail to generate a new mail app password
@@ -712,8 +731,8 @@ class APIClient:
712
731
  :param smtp_allowed: True if the app password should be allowed to use an SMTP server. Default: True
713
732
  :return: the response for the request
714
733
  """
715
- return self.api_request('mail.apppassword.add', {'mail':mail, 'memo':memo,
716
- 'imap_allowed':imap_allowed, 'smtp_allowed':smtp_allowed})
734
+ return self.api_request('mail.apppassword.add', {'mail': mail, 'memo': memo,
735
+ 'imap_allowed': imap_allowed, 'smtp_allowed': smtp_allowed})
717
736
 
718
737
  def mail_apppassword_del(self, apppassword_id: int) -> dict:
719
738
  """
@@ -721,7 +740,7 @@ class APIClient:
721
740
  :param apppassword_id: the id of the mail app password
722
741
  :return: the response for the request
723
742
  """
724
- return self.api_request('mail.apppassword.del', {'id':apppassword_id})
743
+ return self.api_request('mail.apppassword.del', {'id': apppassword_id})
725
744
 
726
745
  def mail_externaluid(self, account: str, uid_extern: str) -> dict:
727
746
  """
@@ -730,7 +749,7 @@ class APIClient:
730
749
  :param uid_extern: the external UID to get a mail for
731
750
  :return: mailbox API response - an array with the mail details
732
751
  """
733
- return self.api_request('mail.externaluid', {'account':account, 'uid_extern':uid_extern})
752
+ return self.api_request('mail.externaluid', {'account': account, 'uid_extern': uid_extern})
734
753
 
735
754
  def mail_backup_list(self, mail: str) -> dict:
736
755
  """
@@ -738,7 +757,7 @@ class APIClient:
738
757
  :param mail: the mail to list backups for
739
758
  :return: mailbox API response - an array with the backup numbers and dates
740
759
  """
741
- return self.api_request('mail.backup.list', {'mail':mail})
760
+ return self.api_request('mail.backup.list', {'mail': mail})
742
761
 
743
762
  def mail_backup_import(self, mail: str, backup_id: str, time: str, backup_filter: str) -> dict:
744
763
  """
@@ -750,7 +769,7 @@ class APIClient:
750
769
  :return: mailbox API response - an array with the backup numbers and dates
751
770
  """
752
771
  return self.api_request('mail.backup.import',
753
- {'mail':mail, 'id':backup_id, 'time':time, 'filter':backup_filter})
772
+ {'mail': mail, 'id': backup_id, 'time': time, 'filter': backup_filter})
754
773
 
755
774
  def mail_spamprotect_get(self, mail: str) -> dict:
756
775
  """
@@ -758,7 +777,7 @@ class APIClient:
758
777
  :param mail: the mail to get the spam settings for
759
778
  :return: mailbox API response - an array with the spam settings
760
779
  """
761
- return self.api_request('mail.spamprotect.get', {'mail':mail})
780
+ return self.api_request('mail.spamprotect.get', {'mail': mail})
762
781
 
763
782
  def mail_spamprotect_set(self, mail: str, greylist: bool, smtp_plausibility: bool, rbl: bool,
764
783
  bypass_banned_checks: bool, tag2level: float, killlevel: str, route_to: str) -> dict:
@@ -778,27 +797,28 @@ class APIClient:
778
797
  raise ValueError('''Invalid value for killlevel. Only 'reject' or 'route' are allowed''')
779
798
 
780
799
  return self.api_request('mail.spamprotect.set',
781
- {'mail':mail, 'greylist': bool2str(greylist),
782
- 'smtp_plausibility':bool2str(smtp_plausibility), 'rbl':bool2str(rbl),
783
- 'bypass_banned_checks':bool2str(bypass_banned_checks), 'tag2level':round(tag2level, 1),
784
- 'killevel':killlevel, 'route_to':route_to})
800
+ {'mail': mail, 'greylist': bool2str(greylist),
801
+ 'smtp_plausibility': bool2str(smtp_plausibility), 'rbl': bool2str(rbl),
802
+ 'bypass_banned_checks': bool2str(bypass_banned_checks),
803
+ 'tag2level': round(tag2level, 1),
804
+ 'killevel': killlevel, 'route_to': route_to})
785
805
 
786
806
  def mail_blacklist_list(self, mail: str) -> dict:
787
807
  """
788
- Function to list the mail blacklist for a given mail address
789
- :param mail: the mail to list the blacklist for
790
- :return: mailbox API response - an array with the complete blacklist of the mail
808
+ Function to list the mail blacklist for a given mail address.
809
+ :param mail: the mail to list the blacklist for.
810
+ :return: mailbox API response - an array with the complete blacklist of the mail.
791
811
  """
792
- return self.api_request('mail.blacklist.list', {'mail':mail})
812
+ return self.api_request('mail.blacklist.list', {'mail': mail})
793
813
 
794
814
  def mail_blacklist_add(self, mail: str, add_address: str) -> dict:
795
815
  """
796
- Function to add a mail to a blacklist of a mail address
797
- :param mail: the mail of the owner of the blacklist
798
- :param add_address: the address to add to the blacklist
799
- :return: mailbox API response - an array with the complete blacklist of the mail
816
+ Function to add a mail to a blacklist of a mail address.
817
+ :param mail: the mail of the owner of the blacklist.
818
+ :param add_address: the address to add to the blacklist.
819
+ :return: mailbox API response - an array with the complete blacklist of the mail.
800
820
  """
801
- return self.api_request('mail.blacklist.add', {'mail':mail, 'add_address':add_address})
821
+ return self.api_request('mail.blacklist.add', {'mail': mail, 'add_address': add_address})
802
822
 
803
823
  def mail_blacklist_del(self, mail: str, delete_address: str) -> dict:
804
824
  """
@@ -807,7 +827,7 @@ class APIClient:
807
827
  :param delete_address: the address to delete from the blacklist
808
828
  :return: mailbox API response - an array with the complete blacklist of the mail
809
829
  """
810
- return self.api_request('mail.blacklist.del', {'mail':mail, 'delete_address':delete_address})
830
+ return self.api_request('mail.blacklist.del', {'mail': mail, 'delete_address': delete_address})
811
831
 
812
832
  def mail_vacation_get(self, mail: str) -> dict:
813
833
  """
@@ -815,10 +835,10 @@ class APIClient:
815
835
  :param mail: the mail to get the vacation notice for
816
836
  :return: mailbox API response - the vacation notice of the mail
817
837
  """
818
- return self.api_request('mail.vacation.get', {'mail':mail})
838
+ return self.api_request('mail.vacation.get', {'mail': mail})
819
839
 
820
840
  def mail_vacation_set(self, mail: str, subject: str, body: str, start_date: str, end_date: str,
821
- additional_mail_addresses: list = None) -> dict:
841
+ additional_mail_addresses: list | None = None) -> dict:
822
842
  """
823
843
  Function to set the vacation notice for a given mail
824
844
  :param mail: the mail to get the vacation notice for
@@ -829,8 +849,8 @@ class APIClient:
829
849
  :param additional_mail_addresses: list of addresses to add to the vacation notice (optional)
830
850
  :return: mailbox API response - array with result 'true' of the request, code and message in case of an error
831
851
  """
832
- params = {'mail':mail, 'subject':subject, 'body':body,'start_date':start_date, 'end_date':end_date,
833
- 'additional_mail_addresses':additional_mail_addresses}
852
+ params = {'mail': mail, 'subject': subject, 'body': body, 'start_date': start_date, 'end_date': end_date,
853
+ 'additional_mail_addresses': additional_mail_addresses}
834
854
 
835
855
  # If no additional_mail_addresses are given, remove the parameter from the request
836
856
  if not additional_mail_addresses:
@@ -838,57 +858,75 @@ class APIClient:
838
858
 
839
859
  return self.api_request('mail.vacation.set', params)
840
860
 
841
- def group_list(self) -> dict:
861
+ def group_list(self, account: str | None = None) -> dict:
842
862
  """
843
863
  Function to list all groups for an account
864
+ :param account: optional parameter for the account to list the groups for
844
865
  :return: mailbox API response - the list of groups
845
866
  """
846
- return self.api_request('group.list', {})
867
+ params = {}
868
+ if account:
869
+ params['account'] = account
870
+ return self.api_request('group.list', params)
847
871
 
848
- def group_get(self, group_id: int) -> dict:
872
+ def group_get(self, group_id: int, account: str | None = None) -> dict:
849
873
  """
850
874
  Function to get a group from the account by the group id
851
875
  :param group_id: the id of the group to get
876
+ :param account: optional parameter for the account to get the group for
852
877
  :return: mailbox API response - the list of groups of the account
853
878
  """
854
- return self.api_request('group.get', {'group_id':group_id})
879
+ params = {'group_id': group_id}
880
+ if account:
881
+ params['account'] = account
882
+ return self.api_request('group.get', params)
855
883
 
856
- def group_del(self, group_id: int) -> dict:
884
+ def group_del(self, group_id: int, account: str | None = None) -> dict:
857
885
  """
858
886
  Function to delete a group
859
887
  :param group_id: the group's id of the group to delete
888
+ :param account: optional parameter for the account to delete the group for
860
889
  :return: mailbox API response - True if the group was deleted, False otherwise
861
890
  """
862
- return self.api_request('group.del', {'group_id':group_id})
891
+ params = {'group_id': group_id}
892
+ if account:
893
+ params['account'] = account
894
+ return self.api_request('group.del', params)
863
895
 
864
- def group_add(self, name: str, display_name: str, mail_addresses_to_add: list) -> dict:
896
+ def group_add(self, name: str, display_name: str, mail_addresses_to_add: list, account: str | None = None) -> dict:
865
897
  """
866
898
  Function to add a group
867
899
  :param name: the group name
868
900
  :param display_name: the group's display name
869
901
  :param mail_addresses_to_add: a list of mail addresses to add
902
+ :param account: optional parameter for the account to add the group for
870
903
  :return: mailbox API response - True if the group was added, False otherwise
871
904
  """
872
- return self.api_request('group.add', {'name':name, 'display_name':display_name,
873
- 'mail_addresses_to_add':mail_addresses_to_add})
905
+ params = {'name': name, 'display_name': display_name, 'mail_addresses_to_add': mail_addresses_to_add}
906
+ if account:
907
+ params['account'] = account
908
+ return self.api_request('group.add', params)
874
909
 
875
- def group_set(self, group_id: int, display_name: str, mail_addresses_to_add: list = None,
876
- mail_addresses_to_remove: list = None) -> dict:
910
+ def group_set(self, group_id: int, display_name: str, mail_addresses_to_add: list | None = None,
911
+ mail_addresses_to_remove: list | None = None, account: str | None = None) -> dict:
877
912
  """
878
913
  Function to modify a group. Either mail_addresses_to_add or mail_addresses_to_remove have to be specified.
879
914
  :param group_id: the group's id of the group to modify
880
915
  :param display_name: the group's display name
881
916
  :param mail_addresses_to_add: a list of mail addresses to add. Defaults to None
882
917
  :param mail_addresses_to_remove: a list of mail addresses to remove. Defaults to None
918
+ :param account: optional parameter for the account to set the group for
883
919
  :return: mailbox API response - True if the group was edited, False otherwise
884
920
  """
885
921
  # If mail_addresses_to_add and mail_addresses_to_remove are both empty, raise error
886
922
  if mail_addresses_to_add is None and mail_addresses_to_remove is None:
887
923
  raise ValueError('mail_addresses_to_add or mail_addresses_to_remove are required')
888
924
 
889
- return self.api_request('group.set', {'group_id':group_id, 'display_name':display_name,
890
- 'mail_addresses_to_add':mail_addresses_to_add,
891
- 'mail_addresses_to_remove':mail_addresses_to_remove})
925
+ params = {'group_id': group_id, 'display_name': display_name, 'mail_addresses_to_add': mail_addresses_to_add,
926
+ 'mail_addresses_to_remove': mail_addresses_to_remove}
927
+ if account:
928
+ params['account'] = account
929
+ return self.api_request('group.set', params)
892
930
 
893
931
  def mail_passwordreset_listmethods(self, mail: str) -> dict:
894
932
  """
@@ -896,16 +934,16 @@ class APIClient:
896
934
  :param mail: the mail to query
897
935
  :return: mailbox API response - a list of available password reset methods
898
936
  """
899
- return self.api_request('mail.passwordreset.listmethods', {'mail':mail})
937
+ return self.api_request('mail.passwordreset.listmethods', {'mail': mail})
900
938
 
901
939
  def mail_passwordreset_sendsms(self, mail: str, cell_phone: str) -> dict:
902
940
  """
903
941
  Function to send a password reset for a mail via SMS
904
942
  :param mail: the mail to send the SMS for
905
943
  :param cell_phone: the cell phone number of the mailbox
906
- :return: mailbox API response - True if the SMS was sent, False otherwise
944
+ :return: API response from mailbox - True if the SMS was sent, False otherwise
907
945
  """
908
- return self.api_request('mail.passwordreset.sendsms',{'mail':mail, 'cell_phone':cell_phone})
946
+ return self.api_request('mail.passwordreset.sendsms', {'mail': mail, 'cell_phone': cell_phone})
909
947
 
910
948
  def mail_passwordreset_setpassword(self, mail: str, token: str, password: str) -> dict:
911
949
  """
@@ -916,7 +954,7 @@ class APIClient:
916
954
  :return: mailbox API response - True if the password was set, False otherwise
917
955
  """
918
956
  return self.api_request('mail.passwordreset.setpassword',
919
- {'mail':mail, 'token':token, 'password':password})
957
+ {'mail': mail, 'token': token, 'password': password})
920
958
 
921
959
  def context_list(self, account: str) -> dict:
922
960
  """
@@ -924,7 +962,7 @@ class APIClient:
924
962
  :param account: the account to list all contexts for
925
963
  :return: mailbox API response - an array with key 'context id' and value 'associated domains'
926
964
  """
927
- return self.api_request('context.list', {'account':account})
965
+ return self.api_request('context.list', {'account': account})
928
966
 
929
967
  def search(self, query: str, get_account_summary: bool = False, get_extended_mail_result: bool = False) -> dict:
930
968
  """
@@ -934,8 +972,8 @@ class APIClient:
934
972
  :param get_extended_mail_result: whether to return more information about mailboxes found
935
973
  :return: the mailbox API response for the request - an array with results for accounts, domains and mailboxes
936
974
  """
937
- return self.api_request('search', {'query':query, 'get_account_summary':get_account_summary,
938
- 'get_extended_mail_result':get_extended_mail_result})
975
+ return self.api_request('search', {'query': query, 'get_account_summary': get_account_summary,
976
+ 'get_extended_mail_result': get_extended_mail_result})
939
977
 
940
978
  def mailinglist_list(self, account: str) -> dict:
941
979
  """
@@ -943,9 +981,9 @@ class APIClient:
943
981
  :param account: the account to list all mailing lists for
944
982
  :return: a dict containing the list of mailing lists
945
983
  """
946
- return self.api_request('mailinglist.list', {'account':account})
984
+ return self.api_request('mailinglist.list', {'account': account})
947
985
 
948
- def mailinglist_add(self, mailinglist: str, password: str, account: str, adminmail: str = None) -> dict:
986
+ def mailinglist_add(self, mailinglist: str, password: str, account: str, adminmail: str | None = None) -> dict:
949
987
  """
950
988
  Function to add a mailing list
951
989
  :param mailinglist: the mailing list to add
@@ -954,8 +992,8 @@ class APIClient:
954
992
  :param adminmail: admin email address of the mailing list (optional)
955
993
  :return: True if the mailing list was added, error code otherwise
956
994
  """
957
- return self.api_request('mailinglist.add', {'mailinglist':mailinglist, 'password':password,
958
- 'account':account, 'adminmail':adminmail})
995
+ return self.api_request('mailinglist.add', {'mailinglist': mailinglist, 'password': password,
996
+ 'account': account, 'adminmail': adminmail})
959
997
 
960
998
  def mailinglist_get(self, mailinglist: str, account: str) -> dict:
961
999
  """
@@ -964,19 +1002,20 @@ class APIClient:
964
1002
  :param account: the account of the mailing list
965
1003
  :return: the mailbox API response for the request - a dict of the mailing list
966
1004
  """
967
- return self.api_request('mailinglist.get', {'mailinglist':mailinglist, 'account':account})
1005
+ return self.api_request('mailinglist.get', {'mailinglist': mailinglist, 'account': account})
968
1006
 
969
- def mailinglist_set(self, mailinglist: str, account: str, password: str = None, adminmail: str = None) -> dict:
1007
+ def mailinglist_set(self, mailinglist: str, account: str, password: str | None = None,
1008
+ adminmail: str | None = None) -> dict:
970
1009
  """
971
- Function to change a mailing list
972
- :param mailinglist: the mailing list to change
973
- :param password: the password of the mailing list
974
- :param account: the account of the mailing list (optional)
975
- :param adminmail: admin email address of the mailing list (optional)
976
- :return: the mailbox API response for the request - True if the mailing list was changed, error code otherwise
1010
+ Function to change a mailing list.
1011
+ :param mailinglist: the mailing list to change.
1012
+ :param password: the password of the mailing list.
1013
+ :param account: the account of the mailing list (optional).
1014
+ :param adminmail: admin email address of the mailing list (optional).
1015
+ :return: the mailbox API response for the request - True if the mailing list was changed, error code otherwise.
977
1016
  """
978
- return self.api_request('mailinglist.set', {'mailinglist':mailinglist, 'account':account,
979
- 'password':password, 'adminmail':adminmail})
1017
+ return self.api_request('mailinglist.set', {'mailinglist': mailinglist, 'account': account,
1018
+ 'password': password, 'adminmail': adminmail})
980
1019
 
981
1020
  def mailinglist_del(self, mailinglist: str, account: str) -> dict:
982
1021
  """
@@ -985,7 +1024,7 @@ class APIClient:
985
1024
  :param account: the account of the mailing list
986
1025
  :return: the mailbox API response for the request - True if the mailing list was deleted, error code otherwise
987
1026
  """
988
- return self.api_request('mailinglist.del', {'mailinglist':mailinglist, 'account':account})
1027
+ return self.api_request('mailinglist.del', {'mailinglist': mailinglist, 'account': account})
989
1028
 
990
1029
  def additionalmailaccount_list(self, parent_mail: str) -> dict:
991
1030
  """
@@ -993,10 +1032,10 @@ class APIClient:
993
1032
  :param parent_mail: the parent mail to list additional mail accounts for
994
1033
  :return: a dict containing the parent mail account and a list of additional mail accounts
995
1034
  """
996
- return self.api_request('additionalmailaccount.list', {'parent_mail':parent_mail})
1035
+ return self.api_request('additionalmailaccount.list', {'parent_mail': parent_mail})
997
1036
 
998
1037
  def additionalmailaccount_add(self, parent_mail: str, new_account_mail: str, new_account_password: str,
999
- primary_address: str = None, mail_server: str = 'imap.mailbox.org',
1038
+ primary_address: str | None = None, mail_server: str = 'imap.mailbox.org',
1000
1039
  mail_port: int = 993, mail_secure: bool = True, mail_starttls: bool = False,
1001
1040
  transport_server: str = 'smtp.mailbox.org', transport_port: int = 465,
1002
1041
  transport_secure: bool = True, transport_starttls: bool = False,
@@ -1009,23 +1048,23 @@ class APIClient:
1009
1048
  2. mail server settings are grouped
1010
1049
  3. transport server settings are grouped
1011
1050
  4. Ports are integers
1012
- :param new_account_mail: the additional mail address to add
1013
- :param new_account_password: the password of the additional mail address
1014
- :param parent_mail: the mail address to add the additional mail account to
1015
- :param primary_address: the primary 'address from' for the additional mail address
1016
- :param mail_server: the IMAP server to use
1017
- :param mail_port: the port of the IMAP server
1018
- :param transport_server: the SMTP server to use
1019
- :param transport_port: the port of the SMTP server
1020
- :param mail_secure: whether to use SSL for IMAP
1021
- :param mail_starttls: whether to use STARTTLS for IMAP
1022
- :param transport_secure: whether to use SSL for SMTP
1023
- :param transport_starttls: whether to use STARTTLS for SMTP
1024
- :param trash_folder: name of the trash folder
1025
- :param sent_folder: name of the sent folder
1026
- :param drafts_folder: name of the drafts folder
1027
- :param spam_folder: name of the spam folder
1028
- :return: the response for the request - True if adding was successful, error code otherwise
1051
+ :param new_account_mail: the additional mail address to add.
1052
+ :param new_account_password: the password of the additional mail address.
1053
+ :param parent_mail: the mail address to add the additional mail account to.
1054
+ :param primary_address: the primary 'address from' for the additional mail address.
1055
+ :param mail_server: the IMAP server to use.
1056
+ :param mail_port: the port of the IMAP server.
1057
+ :param transport_server: the SMTP server to use.
1058
+ :param transport_port: the port of the SMTP server.
1059
+ :param mail_secure: whether to use SSL for IMAP.
1060
+ :param mail_starttls: whether to use STARTTLS for IMAP.
1061
+ :param transport_secure: whether to use SSL for SMTP.
1062
+ :param transport_starttls: whether to use STARTTLS for SMTP.
1063
+ :param trash_folder: name of the trash folder.
1064
+ :param sent_folder: name of the sent folder.
1065
+ :param drafts_folder: name of the drafts folder.
1066
+ :param spam_folder: name of the spam folder.
1067
+ :return: the response for the request - True if adding was successful, error code otherwise.
1029
1068
  """
1030
1069
  return self.api_request('additionalmailaccount.add', {'new_account_mail': new_account_mail,
1031
1070
  'new_account_password': new_account_password,
@@ -1051,7 +1090,7 @@ class APIClient:
1051
1090
  :return: True if the account was deleted, error code otherwise
1052
1091
  """
1053
1092
  return self.api_request('additionalmailaccount.delete',
1054
- {'parent_mail':parent_mail, 'account_mail':account_mail})
1093
+ {'parent_mail': parent_mail, 'account_mail': account_mail})
1055
1094
 
1056
1095
  def evac_activate(self):
1057
1096
  """
@@ -1061,7 +1100,7 @@ class APIClient:
1061
1100
  """
1062
1101
  return self.api_request('evac_activate', {})
1063
1102
 
1064
- def evac_resetaccount(self, delete_mail_accounts_and_domains:bool = False) -> dict:
1103
+ def evac_resetaccount(self, delete_mail_accounts_and_domains: bool = False) -> dict:
1065
1104
  """
1066
1105
  Function to reset a mailbox EVAC account.
1067
1106
  Note: this needs a special permission from mailbox.
@@ -1071,6 +1110,7 @@ class APIClient:
1071
1110
  return self.api_request('evac_resetaccount',
1072
1111
  {'delete_mail_accounts_and_domains': delete_mail_accounts_and_domains})
1073
1112
 
1113
+
1074
1114
  def validate_params(allowed: dict, actual: dict) -> bool | None:
1075
1115
  for arg in actual:
1076
1116
  if arg not in allowed:
@@ -1082,6 +1122,7 @@ def validate_params(allowed: dict, actual: dict) -> bool | None:
1082
1122
  return True
1083
1123
  return None
1084
1124
 
1125
+
1085
1126
  def bool2str(state: bool) -> str:
1086
1127
  """
1087
1128
  Converts a boolean value to '1' if True, and '0' if False...
@@ -1089,4 +1130,4 @@ def bool2str(state: bool) -> str:
1089
1130
  """
1090
1131
  if state:
1091
1132
  return '1'
1092
- return '0'
1133
+ return '0'
@@ -1,4 +1,5 @@
1
1
  class APIError(Exception):
2
2
  """Custom exception for API errors."""
3
+
3
4
  def __init__(self, message, code=None):
4
- super().__init__(f'Error {code} - {message}')
5
+ super().__init__(f'Error {code} - {message}')
@@ -80,4 +80,4 @@ class Invoice:
80
80
  # Add each attribute to the String.
81
81
  # As the attribute name is '_attribute', remove the leading character
82
82
  print_string += f'{k[1:]}: {v}\n'
83
- return print_string
83
+ return print_string
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mailbox-org-api
3
- Version: 2.2
4
- Summary: A library to access the mailbox.org Business API.
3
+ Version: 2.4
4
+ Summary: A library to access the mailbox Business API.
5
5
  Author: Hendrik Schlange
6
6
  Author-email: Hendrik Schlange <mail@heshsum.de>
7
7
  Project-URL: Homepage, https://github.com/heshsum/mailbox-org-api
@@ -36,11 +36,15 @@ pip install mailbox-org-api
36
36
  pip install git+https://github.com/heshsum/mailbox-org-api
37
37
  ```
38
38
 
39
- ## Usage
39
+ ## Usage and documentation
40
40
  Basic usage is fairly straightforward. The naming scheme of the functions is similar to the naming at mailbox.org,
41
- but instead of points, it uses underscores (e.g. instead of `mail.add` it's `mail_add`).
41
+ but instead of points, it uses underscores (e.g. instead of `mail.add` it's `mail_add`).
42
+
43
+ Therefore, the functions mirror the functions as provided and documented at mailbox:
44
+ [api.mailbox.org](https://api.mailbox.org)
45
+
42
46
  Additionally, some helper functions for common or more complicated tasks are included to make life a bit easier,
43
- e.g. for changing plans, password and to retrieve invoices.
47
+ e.g. for changing plans, password and to retrieving invoices.
44
48
 
45
49
  ```python
46
50
  from mailbox_org_api import APIClient
@@ -87,6 +91,8 @@ api.mail_set_forwards('foo@bar.com', ['forward1@bar.com', 'forward2@bar.com'])
87
91
  api.deauth()
88
92
  ```
89
93
 
94
+ More information can be found in the [Wiki](https://github.com/heshsum/mailbox-org-api/wiki)
95
+
90
96
  ## Common tasks
91
97
  mailbox_org_api includes a number of helper functions to make common tasks simpler. These include:
92
98
 
@@ -163,21 +169,21 @@ Usage:
163
169
  api.account_invoice_get_token('BMBO-1234-24')
164
170
  ```
165
171
 
166
- ### account_invoice_get_pdf
172
+ ### account_invoice_get_file
167
173
  Invoices are provided as Based64 encoded gz Strings. This function
168
174
  1. takes the invoice ID
169
175
  2. retrieves the token for the invoice
170
176
  3. gets the binary data
171
177
  4. decodes the Base64
172
178
  5. decompresses it
173
- 6. returns the bytes of the actual PDF
179
+ 6. returns the bytes of the actual invoice file
174
180
 
175
181
  Usage
176
182
  ```python
177
183
  invoice_id = 'BMBO-1234-24'
178
- account_name = 'some_user'
184
+ account_name = 'foo'
179
185
  with open(invoice_id + '.pdf', 'w') as file:
180
- file.write(api.account_invoice_get_pdf(account_name, invoice_id))
186
+ file.write(api.account_invoice_get_file(account_name, invoice_id, 'PDF'))
181
187
  ```
182
188
 
183
189
  ## Here be dragons
@@ -1,10 +1,10 @@
1
1
  [project]
2
2
  name = "mailbox-org-api"
3
- version = "2.2"
3
+ version = "2.4"
4
4
  authors = [
5
5
  { name="Hendrik Schlange", email="mail@heshsum.de" },
6
6
  ]
7
- description = "A library to access the mailbox.org Business API."
7
+ description = "A library to access the mailbox Business API."
8
8
  readme = "README.md"
9
9
  requires-python = ">=3.11"
10
10
  classifiers = [
@@ -3,8 +3,8 @@ from setuptools import find_packages, setup
3
3
  setup(
4
4
  name='mailbox_org_api',
5
5
  packages=find_packages(),
6
- version='2.2',
7
- description='A library to access the mailbox.org Business API',
6
+ version='2.4',
7
+ description='A library to access the mailbox Business API',
8
8
  author='Hendrik Schlange',
9
9
  install_requires=['requests'],
10
10
  tests_require=['pytest'],
@@ -1,19 +1,23 @@
1
- from mailbox_org_api import APIClient
2
- from mailbox_org_api.APIError import APIError
3
- import pytest
4
1
  import os
5
- import time
6
2
  import secrets
7
3
  import string
4
+ import time
5
+
6
+ import pytest
7
+
8
+ from mailbox_org_api import APIClient
9
+ from mailbox_org_api.APIError import APIError
8
10
 
9
11
  api_test_user = os.environ['API_TEST_USER']
10
12
  api_test_pass = os.environ['API_TEST_PASS']
11
13
 
14
+
12
15
  # Create a unique ID String by using the Unix time,
13
16
  # converted to int (to get rid of the decimal) and then to String
14
17
  def generate_id():
15
18
  return str(int(time.time()))
16
19
 
20
+
17
21
  def generate_pw():
18
22
  # Length of password
19
23
  length = 42
@@ -36,6 +40,7 @@ def generate_pw():
36
40
  any(c in special for c in pw)):
37
41
  return pw
38
42
 
43
+
39
44
  def get_domain():
40
45
  api = APIClient.APIClient()
41
46
  api.auth(api_test_user, api_test_pass)
@@ -43,16 +48,18 @@ def get_domain():
43
48
  api.deauth()
44
49
  return domain
45
50
 
51
+
46
52
  test_id = generate_id()
47
53
  domain = get_domain()
48
54
 
55
+
49
56
  class TestAPIClient:
50
57
  def test_validate_params(self):
51
58
  allowed = {'string': str}
52
59
  with pytest.raises(ValueError):
53
- APIClient.validate_params(allowed, {'integer':123})
60
+ APIClient.validate_params(allowed, {'integer': 123})
54
61
  with pytest.raises(TypeError):
55
- APIClient.validate_params(allowed, {'string':123})
62
+ APIClient.validate_params(allowed, {'string': 123})
56
63
 
57
64
  def test_headers(self):
58
65
  api = APIClient.APIClient()
@@ -195,7 +202,7 @@ class TestAPIClient:
195
202
  api.auth(api_test_user, api_test_pass)
196
203
  invoice = api.account_invoice_get_list(api_test_user)[0]
197
204
  token = api.account_invoice_get_token(api_test_user, invoice_id=invoice)
198
- assert len(token) >0
205
+ assert len(token) > 0
199
206
  assert isinstance(token, str)
200
207
  api.deauth()
201
208
 
@@ -210,6 +217,16 @@ class TestAPIClient:
210
217
  assert isinstance(d['count_mails'], int)
211
218
  api.deauth()
212
219
 
220
+ def test_domain_get_list(self):
221
+ api = APIClient.APIClient()
222
+ api.auth(api_test_user, api_test_pass)
223
+ domain_names = api.domain_get_list(api_test_user)
224
+ domains = api.domain_list(api_test_user)
225
+ assert len(domain_names) == len(domains)
226
+ for d in domains:
227
+ assert d['domain'] in domain_names
228
+ api.deauth()
229
+
213
230
  def test_domain_get(self):
214
231
  api = APIClient.APIClient()
215
232
  api.auth(api_test_user, api_test_pass)
@@ -257,13 +274,24 @@ class TestAPIClient:
257
274
  assert paginated_mails['totalPages'] is not None
258
275
  assert paginated_mails['results'] is not None
259
276
  with pytest.raises(APIError):
260
- api.mail_list(domain, page = 2)
277
+ api.mail_list(domain, page=2)
261
278
  with pytest.raises(APIError):
262
279
  api.mail_list(domain, page_size=-1)
263
280
  with pytest.raises(ValueError):
264
281
  api.mail_list(domain, sort_order='wröng')
265
282
  api.deauth()
266
283
 
284
+ def test_mail_get_list(self):
285
+ api = APIClient.APIClient()
286
+ api.auth(api_test_user, api_test_pass)
287
+ mails = api.mail_list(domain)
288
+ mail_addresses = api.mail_get_list(domain)
289
+ assert len(mail_addresses) == len(mails)
290
+ for i in mails:
291
+ assert i['mail'] is not None
292
+ assert i['mail'] in mail_addresses
293
+ api.deauth()
294
+
267
295
  def test_mail_get(self):
268
296
  api = APIClient.APIClient()
269
297
  api.auth(api_test_user, api_test_pass)
@@ -318,8 +346,8 @@ class TestAPIClient:
318
346
  'aliases': [test_id + '_alias@' + domain], 'alternate_mail': test_id + '_alternate@' + domain,
319
347
  'memo': 'memo_string', 'active': True, 'title': 'Title', 'position': 'Job Position',
320
348
  'department': 'Department', 'company': 'Company', 'street': 'Street 1',
321
- 'postal_code': '12345', 'city': 'City', 'phone':'+492345678', 'fax':'+492345678',
322
- 'cell_phone':'+492345678', 'uid_extern': 'external_uid_value', 'language': 'de_DE'}
349
+ 'postal_code': '12345', 'city': 'City', 'phone': '+492345678', 'fax': '+492345678',
350
+ 'cell_phone': '+492345678', 'uid_extern': 'external_uid_value', 'language': 'de_DE'}
323
351
 
324
352
  # Adding parameters to call
325
353
  params = {}
@@ -340,7 +368,7 @@ class TestAPIClient:
340
368
  api.mail_set(mail, additional_cloud_quota=5)
341
369
 
342
370
  with pytest.raises(KeyError):
343
- api.mail_set(mail, additional_mail_quota = 5, additional_cloud_quota=5)
371
+ api.mail_set(mail, additional_mail_quota=5, additional_cloud_quota=5)
344
372
 
345
373
  api.deauth()
346
374
 
@@ -2,6 +2,7 @@ from mailbox_org_api import Account
2
2
 
3
3
  account_name = 'heiner.hansen'
4
4
 
5
+
5
6
  class TestAccount:
6
7
  def test_account(self):
7
8
  account = Account.Account(account_name)
@@ -80,8 +81,8 @@ class TestAccount:
80
81
  def test_account_contact(self):
81
82
  account = Account.Account(account_name)
82
83
  assert account.contact == {}
83
- contact = {'mail':'contact@tests.internal', 'first_name': 'Test', 'last_name': 'Contact', 'birthday': '',
84
- 'street':'Teststr. 1', 'zipcode':'12345', 'town':'Testtown', 'country':'DE'}
84
+ contact = {'mail': 'contact@tests.internal', 'first_name': 'Test', 'last_name': 'Contact', 'birthday': '',
85
+ 'street': 'Teststr. 1', 'zipcode': '12345', 'town': 'Testtown', 'country': 'DE'}
85
86
  account.contact = contact
86
87
  assert account.contact == contact
87
88
 
@@ -3,6 +3,7 @@ from mailbox_org_api import Invoice
3
3
  test_account = 'test_account'
4
4
  test_id = 'BMBO-1234-2025'
5
5
 
6
+
6
7
  class TestMail:
7
8
 
8
9
  def test_invoice_create(self):
@@ -43,4 +44,4 @@ class TestMail:
43
44
  assert invoice.token is None
44
45
  token = '123456789'
45
46
  invoice.token = token
46
- assert invoice.token == token
47
+ assert invoice.token == token
@@ -1,8 +1,10 @@
1
- from mailbox_org_api import Mail
2
1
  import unittest
3
2
 
3
+ from mailbox_org_api import Mail
4
+
4
5
  mail_address = 'tests@tests.tests'
5
6
 
7
+
6
8
  class TestMail(unittest.TestCase):
7
9
 
8
10
  def test_init(self):
File without changes
File without changes