Frappe Mail - self host

After mail install on the site, trying to add domain, But getting the following error
Cluster is not set for Mail Tenant 9466gm9bet .
Any idea
Self hosted on VPS

ERROR LOGS

Traceback with variables (most recent call last):
  File "apps/frappe/frappe/app.py", line 116, in application
    response = frappe.api.handle(request)
      request = <Request 'http://mail.testxyzdemo.com:8000/api/method/mail.api.admin.verify_dns_record' [POST]>
      response = None
      rollback = True
      e = ValidationError('Cluster is not set for Mail Tenant <strong>9466gm9bet</strong>.')
  File "apps/frappe/frappe/api/__init__.py", line 49, in handle
    data = endpoint(**arguments)
      request = <Request 'http://mail.testxyzdemo.com:8000/api/method/mail.api.admin.verify_dns_record' [POST]>
      endpoint = <function handle_rpc_call at 0x72ac87378c20>
      arguments = {'method': 'mail.api.admin.verify_dns_record'}
  File "apps/frappe/frappe/api/v1.py", line 36, in handle_rpc_call
    return frappe.handler.handle()
      method = 'mail.api.admin.verify_dns_record'
      frappe = <module 'frappe' from 'apps/frappe/frappe/__init__.py'>
  File "apps/frappe/frappe/handler.py", line 51, in handle
    data = execute_cmd(cmd)
      cmd = 'mail.api.admin.verify_dns_record'
      data = None
  File "apps/frappe/frappe/handler.py", line 84, in execute_cmd
    return frappe.call(method, **frappe.form_dict)
      cmd = 'mail.api.admin.verify_dns_record'
      from_async = False
      server_script = None
      method = <function verify_dns_record at 0x72ac77332840>
  File "apps/frappe/frappe/__init__.py", line 1461, in call
    return fn(*args, **newargs)
      fn = <function verify_dns_record at 0x72ac77332840>
      args = ()
      kwargs = {'domain_request': 'hb6uu8019p', 'cmd': 'mail.api.admin.verify_dns_record'}
      newargs = {'domain_request': 'hb6uu8019p'}
  File "apps/frappe/frappe/utils/typing_validations.py", line 32, in wrapper
    return func(*args, **kwargs)
      args = []
      kwargs = {'domain_request': 'hb6uu8019p'}
      apply_condition = <function whitelist.<locals>.innerfn.<locals>.<lambda> at 0x72ac773337e0>
      func = <function verify_dns_record at 0x72ac77332ac0>
  File "apps/mail/mail/utils/rate_limiter.py", line 42, in wrapper
    return wrapped_fn(*args, **kwargs)
      args = ()
      kwargs = {'domain_request': 'hb6uu8019p'}
      wrapped_fn = <function verify_dns_record at 0x72ac77332a20>
      method_path = 'mail.api.admin.verify_dns_record'
      rate_limits = [{'ignore_in_developer_mode': True, 'key': None, 'limit': 10, 'seconds': 3600, 'methods': 'ALL', 'ip_based': True, 'allowed_ips': [], 'blocked_ips': []}]
      rl = {'ignore_in_developer_mode': True, 'key': '********', 'limit': 10, 'seconds': 3600, 'methods': 'ALL', 'ip_based': True, 'allowed_ips': [], 'blocked_ips': []}
      request_ip = '127.0.0.1'
      fn = <function verify_dns_record at 0x72ac77332a20>
  File "apps/mail/mail/api/admin.py", line 50, in verify_dns_record
    return doc.verify_and_create_domain(save=True)
      domain_request = 'hb6uu8019p'
      doc = <MailDomainRequest: doctype=Mail Domain Request hb6uu8019p>
  File "apps/frappe/frappe/utils/typing_validations.py", line 32, in wrapper
    return func(*args, **kwargs)
      args = [<MailDomainRequest: doctype=Mail Domain Request hb6uu8019p>]
      kwargs = {'save': True}
      apply_condition = <function whitelist.<locals>.innerfn.<locals>.<lambda> at 0x72ac844f8720>
      func = <function MailDomainRequest.verify_and_create_domain at 0x72ac844fbb00>
  File "apps/mail/mail/mail/doctype/mail_domain_request/mail_domain_request.py", line 75, in verify_and_create_domain
    self.create_domain()
      self = <MailDomainRequest: doctype=Mail Domain Request hb6uu8019p>
      save = True
  File "apps/mail/mail/mail/doctype/mail_domain_request/mail_domain_request.py", line 91, in create_domain
    domain.insert(ignore_permissions=True)
      self = <MailDomainRequest: doctype=Mail Domain Request hb6uu8019p>
      domain = <MailDomain: doctype=Mail Domain unsaved>
  File "apps/frappe/frappe/model/document.py", line 408, in insert
    self.run_method("before_insert")
      self = <MailDomain: doctype=Mail Domain unsaved>
      ignore_permissions = True
      ignore_links = None
      ignore_if_duplicate = False
      ignore_mandatory = None
      set_name = None
      set_child_names = True
  File "apps/frappe/frappe/model/document.py", line 1128, in run_method
    out = Document.hook(fn)(self, *args, **kwargs)
      self = <MailDomain: doctype=Mail Domain unsaved>
      method = 'before_insert'
      args = ()
      kwargs = {}
      fn = <function Document.run_method.<locals>.fn at 0x72ac841f1bc0>
  File "apps/frappe/frappe/model/document.py", line 1517, in composer
    return composed(self, method, *args, **kwargs)
      self = <MailDomain: doctype=Mail Domain unsaved>
      args = ()
      kwargs = {}
      hooks = []
      method = 'before_insert'
      doc_events = {'*': {'on_update': ['frappe.desk.notifications.clear_doctype_notifications', 'frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions', 'frappe.core.doctype.file.utils.attach_files_to_document', 'frappe.automation.doctype.assignment_rule.assignment_rule.apply', 'frappe.automation.doctype.assignment_rule.assignment_rule.update_due_date', 'frappe.core.doctype.user_type.user_type.apply_permissions_for_non_standard_user_type', 'frappe.core.doctype.permission_log.permission_log.make_perm_log'], 'after_rename': ['frappe.desk.notifications.clear_doctype_notifications'], 'on_cancel': ['frappe.desk.notifications.clear_doctype_notifications', 'frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions', 'frappe.automation.doctype.assignment_rule.assignment_rule.apply'], 'on_trash': ['frappe.desk.notifications.clear_doctype_notifications', 'frappe.workflow.doctype.workflow_action.workflow_action.process_workflow_actions'], 'on_update_after_submit': ...
      composed = <function Document.hook.<locals>.compose.<locals>.runner at 0x72ac764859e0>
      compose = <function Document.hook.<locals>.compose at 0x72ac76486200>
      f = <function Document.run_method.<locals>.fn at 0x72ac841f1bc0>
  File "apps/frappe/frappe/model/document.py", line 1495, in runner
    add_to_return_value(self, fn(self, *args, **kwargs))
      self = <MailDomain: doctype=Mail Domain unsaved>
      method = 'before_insert'
      args = ()
      kwargs = {}
      add_to_return_value = <function Document.hook.<locals>.add_to_return_value at 0x72ac8428bb00>
      fn = <function Document.run_method.<locals>.fn at 0x72ac841f1bc0>
      hooks = ()
  File "apps/frappe/frappe/model/document.py", line 1125, in fn
    return method_object(*args, **kwargs)
      self = <MailDomain: doctype=Mail Domain unsaved>
      args = ()
      kwargs = {}
      method_object = <bound method MailDomain.before_insert of <MailDomain: doctype=Mail Domain unsaved>>
      method = 'before_insert'
  File "apps/mail/mail/mail/doctype/mail_domain/mail_domain.py", line 29, in before_insert
    self.validate_tenant()
      self = <MailDomain: doctype=Mail Domain unsaved>
  File "apps/mail/mail/mail/doctype/mail_domain/mail_domain.py", line 78, in validate_tenant
    frappe.throw(_("Cluster is not set for Mail Tenant {0}.").format(frappe.bold(self.tenant)))
      self = <MailDomain: doctype=Mail Domain unsaved>
      cluster = None
      max_domains = 10
  File "apps/frappe/frappe/utils/messages.py", line 145, in throw
    msgprint(
      msg = 'Cluster is not set for Mail Tenant <strong>9466gm9bet</strong>.'
      exc = <class 'frappe.exceptions.ValidationError'>
      title = None
      is_minimizable = False
      wide = False
      as_list = False
      primary_action = None
  File "apps/frappe/frappe/utils/messages.py", line 106, in msgprint
    _raise_exception()
      msg = 'Cluster is not set for Mail Tenant <strong>9466gm9bet</strong>.'
      title = None
      raise_exception = <class 'frappe.exceptions.ValidationError'>
      as_table = False
      as_list = False
      indicator = 'red'
      alert = False
      primary_action = None
      is_minimizable = False
      wide = False
      realtime = False
      _raise_exception = <function msgprint.<locals>._raise_exception at 0x72ac8526e0c0>
      inspect = <module 'inspect' from '/home/frappe/.pyenv/versions/3.11.6/lib/python3.11/inspect.py'>
      out = {'message': 'Cluster is not set for Mail Tenant <strong>9466gm9bet</strong>.', 'title': 'Message', 'indicator': 'red', 'raise_exception': 1, '__frappe_exc_id': 'd251cc1fb75d2ea265d528809ff775201a723072e4a9fc9ceeded1ac'}
  File "apps/frappe/frappe/utils/messages.py", line 57, in _raise_exception
    raise exc
      exc = ValidationError('Cluster is not set for Mail Tenant <strong>9466gm9bet</strong>.')
      inspect = <module 'inspect' from '/home/frappe/.pyenv/versions/3.11.6/lib/python3.11/inspect.py'>
      msg = 'Cluster is not set for Mail Tenant <strong>9466gm9bet</strong>.'
      out = {'message': 'Cluster is not set for Mail Tenant <strong>9466gm9bet</strong>.', 'title': 'Message', 'indicator': 'red', 'raise_exception': 1, '__frappe_exc_id': 'd251cc1fb75d2ea265d528809ff775201a723072e4a9fc9ceeded1ac'}
      raise_exception = <class 'frappe.exceptions.ValidationError'>
frappe.exceptions.ValidationError: Cluster is not set for Mail Tenant <strong>9466gm9bet</strong>.

@Sagar_Patil Thanks for the frappe mail.
Need some help on this
Followed this doc

install Install Stalwart Mail Server on digital ocean vps.
And frappe mail hosted/install in different VPS with other provider.
frappe mail installed sucessfully.
While verifying domain getting the following error.
" Cluster is not set for Mail Tenant 9466gm9bet ."

Can someone explain me Frappe Mail in simple terms?
We already can send and receive mails.

@Venkatesan

Go to Mail Tenant → Frappe Mail, and set the Cluster (Link Field) that you created earlier.

The documentation (README.md) is currently outdated and will be updated shortly.

1 Like

@TurkerTunali

Frappe Mail simplifies self-hosting an email system by acting as an orchestrator. The goal is to offer a fully automated solution, allowing you to deploy and manage mail servers effortlessly through a user-friendly interface. Interestingly, it has a built-in mail client (web) powered by Frappe UI.

2 Likes

Thanks @Sagar_Sharma , Will wait for updated documentation

Now, that makes sense.

@Venkatesan You can also check out this video for reference.