Ejemplo n.º 1
0
 def get_header(self, msg, header):
     # msg parameter to maintain compatibility with
     # modoboa_webmail.lib.imapemail.ImapEmail
     if header in msg:
         decoded_values = []
         for value, encoding in email.header.decode_header(msg[header]):
             if not len(value):
                 continue
             if encoding:
                 value = smart_text(value, encoding=encoding)
             elif isinstance(value, six.binary_type):
                 # SMTPUTF8 fallback (most of the time)
                 # Address contains non ASCII chars but is not RFC2047
                 # encoded...
                 encoding = chardet.detect(value)
                 try:
                     value = value.decode(encoding["encoding"], "replace")
                 except (TypeError, UnicodeDecodeError) as exc:
                     six.raise_from(
                         InternalError(
                             _("unable to determine encoding of string")
                         ),
                         exc
                     )
             decoded_values.append(value)
         return "".join(decoded_values)
     return ""
Ejemplo n.º 2
0
    def mail_home(self):
        """Retrieve the home directory of this mailbox.
 
        The home directory refers to the place on the file system
        where the mailbox data is stored.

        We ask dovecot to give us this information because there are
        several patterns to understand and we don't want to implement
        them.        
        """
        hm = parameters.get_admin("HANDLE_MAILBOXES", raise_error=False)
        if hm is None or hm == "no":
            return None
        if self.__mail_home is None:
            curuser = pwd.getpwuid(os.getuid()).pw_name
            mbowner = parameters.get_admin("MAILBOXES_OWNER")
            options = {}
            if curuser != mbowner:
                options['sudo_user'] = mbowner
            code, output = exec_cmd(
                "doveadm user %s -f home" % self.full_address, **options)
            if code:
                raise InternalError(
                    _("Failed to retrieve mailbox location (%s)" % output))
            self.__mail_home = output.strip()
        return self.__mail_home
Ejemplo n.º 3
0
 def _get_domain_from_rcpt(self, rcpt):
     """Retrieve a domain from a recipient address."""
     local_part, domname = split_mailbox(rcpt)
     domain = admin_models.Domain.objects.filter(name=domname).first()
     if not domain:
         raise InternalError(_("Local domain not found"))
     return domain
Ejemplo n.º 4
0
    def hdelimiter(self):
        """Return the default hierachy delimiter.

        :return: a string
        """
        if self.__hdelimiter is None:
            raise InternalError(_("Failed to retrieve hierarchy delimiter"))
        return self.__hdelimiter
Ejemplo n.º 5
0
def init_storage_dir():
    """Create the directory whare documents will be stored."""
    storage_dir = parameters.get_admin("STORAGE_DIR")
    if os.path.exists(storage_dir):
        return
    try:
        os.mkdir(storage_dir)
    except (OSError, IOError) as inst:
        raise InternalError(
            _("Failed to create the directory that will contain "
              "PDF documents (%s)") % inst)
Ejemplo n.º 6
0
 def _find_binary(self, name):
     """Find path to binary."""
     code, output = exec_cmd("which {}".format(name))
     if not code:
         return smart_text(output).strip()
     known_paths = getattr(settings, "SA_LOOKUP_PATH", ("/usr/bin", ))
     for path in known_paths:
         bpath = os.path.join(path, name)
         if os.path.isfile(bpath) and os.access(bpath, os.X_OK):
             return bpath
     raise InternalError(_("Failed to find {} binary").format(name))
Ejemplo n.º 7
0
def delete_ldap_account(user, config):
    """Delete remote LDAP account."""
    dn = config["ldap_sync_account_dn_template"] % {"user": user.username}
    conn = get_connection(config)
    if not check_if_dn_exists(conn, dn):
        return
    if config["ldap_sync_delete_remote_account"]:
        try:
            conn.delete_s(dn)
        except ldap.LDAPError as e:
            raise InternalError(
                _("Failed to delete LDAP account: {}").format(e))
    else:
        password = get_user_password(user, True)
        ldif = [(ldap.MOD_REPLACE, "userPassword", password)]
        try:
            conn.modify_s(dn, ldif)
        except ldap.LDAPError as e:
            raise InternalError(
                _("Failed to disable LDAP account: {}").format(e))
Ejemplo n.º 8
0
 def update_user_password(self, user, password, newpassword):
     try:
         self.connect_to_server(user, password)
         if self.ldap_ad:
             newpassword = ((
                 '"%s"' % newpassword).encode('utf-16').lstrip('\377\376'))
         ldif = [(ldap.MOD_REPLACE, self.pwd_attr,
                  self._crypt_password(newpassword))]
         self.conn.modify_s(self.user_dn, ldif)
     except ldap.LDAPError as e:
         raise InternalError(_("Failed to update password: %s" % str(e)))
Ejemplo n.º 9
0
 def __init__(self):
     conf = dict(param_tools.get_global_parameters("modoboa_amavis"))
     try:
         if conf["am_pdp_mode"] == "inet":
             self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
             self.sock.connect((conf["am_pdp_host"], conf["am_pdp_port"]))
         else:
             self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
             self.sock.connect(conf["am_pdp_socket"])
     except socket.error as err:
         raise InternalError(_("Connection to amavis failed: %s" %
                               str(err)))
Ejemplo n.º 10
0
 def update_user_password(self, user, password, newpassword):
     """Update user password."""
     self.connect_to_server(user, password)
     user_dn = self._find_user_dn(user)
     if self.ldap_ad:
         newpassword = (('"%s"' %
                         newpassword).encode('utf-16').lstrip('\377\376'))
     ldif = [(ldap.MOD_REPLACE, self.pwd_attr,
              self._crypt_password(newpassword))]
     try:
         self.conn.modify_s(user_dn, ldif)
     except ldap.LDAPError as e:
         raise InternalError(_("Failed to update password: {}").format(e))
Ejemplo n.º 11
0
    def hdelimiter(self):
        """Return the default hierachy delimiter.

        This is a simple way to retrieve the default delimiter (see
        http://www.imapwiki.org/ClientImplementation/MailboxList).

        :return: a string
        """
        if self.__hdelimiter is None:
            data = self._cmd("LIST", "", "")
            m = self.list_response_pattern.match(data[0])
            if m is None:
                raise InternalError(_("Failed to retrieve hierarchy delimiter"))
            self.__hdelimiter = m.group('delimiter')
        return self.__hdelimiter
Ejemplo n.º 12
0
def db_type(cname="default"):
    """Return the type of the *default* database

    Supported values : 'postgres', 'mysql', 'sqlite'

    :param str cname: connection name
    :return: a string or None
    """
    if cname not in settings.DATABASES:
        raise InternalError(
            _("Connection to database %s not configured" % cname))
    for t in ["postgres", "mysql", "sqlite"]:
        if settings.DATABASES[cname]["ENGINE"].find(t) != -1:
            return t
    return None
Ejemplo n.º 13
0
 def __init__(self):
     mode = parameters.get_admin("AM_PDP_MODE")
     try:
         if mode == "inet":
             host = parameters.get_admin('AM_PDP_HOST')
             port = parameters.get_admin('AM_PDP_PORT')
             self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
             self.sock.connect((host, int(port)))
         else:
             path = parameters.get_admin('AM_PDP_SOCKET')
             self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
             self.sock.connect(path)
     except socket.error, err:
         raise InternalError(_("Connection to amavis failed: %s" %
                               str(err)))
Ejemplo n.º 14
0
Archivo: lib.py Proyecto: finid/modoboa
 def _get_mailbox_from_rcpt(self, rcpt):
     """Retrieve a mailbox from a recipient address."""
     local_part, domname = split_mailbox(rcpt)
     try:
         mailbox = Mailbox.objects.select_related("domain").get(
             address=local_part, domain__name=domname)
     except Mailbox.DoesNotExist:
         try:
             alias = Alias.objects.select_related("domain").get(
                 address=local_part, domain__name=domname)
         except Alias.DoesNotExist:
             raise InternalError(_("No recipient found"))
         if alias.type != "alias":
             return None
         mailbox = alias.mboxes.all()[0]
     return mailbox
Ejemplo n.º 15
0
def decode(value_bytes, encoding, append_to_error=""):
    """Try to decode the given string."""
    assert isinstance(value_bytes, bytes),\
        "value_bytes should be of type bytes"
    if len(value_bytes) == 0:
        # short circuit for empty strings
        return ""
    try:
        value = value_bytes.decode(encoding)
    except (UnicodeDecodeError, LookupError):
        encoding = chardet.detect(value_bytes)
        try:
            value = value_bytes.decode(encoding["encoding"], "replace")
        except (TypeError, UnicodeDecodeError) as exc:
            raise InternalError(
                _("unable to determine encoding of string") +
                append_to_error) from exc
    return value
Ejemplo n.º 16
0
 def _get_mailbox_from_rcpt(self, rcpt):
     """Retrieve a mailbox from a recipient address."""
     local_part, domname, extension = (split_mailbox(rcpt,
                                                     return_extension=True))
     try:
         mailbox = admin_models.Mailbox.objects.select_related(
             "domain").get(address=local_part, domain__name=domname)
     except admin_models.Mailbox.DoesNotExist:
         alias = admin_models.Alias.objects.filter(
             address="{}@{}".format(local_part, domname),
             aliasrecipient__r_mailbox__isnull=False).first()
         if not alias:
             raise InternalError(_("No recipient found"))
         if alias.type != "alias":
             return None
         mailbox = alias.aliasrecipient_set.filter(
             r_mailbox__isnull=False).first()
     return mailbox
Ejemplo n.º 17
0
    def set_password(self, raw_value, curvalue=None):
        """Password update

        Update the current mailbox's password with the given clear
        value. This value is encrypted according to the defined method
        before it is saved.

        :param raw_value: the new password's value
        :param curvalue: the current password (for LDAP authentication)
        """
        if self.is_local:
            self.password = self._crypt_password(raw_value)
        else:
            if not ldap_available:
                raise InternalError(
                    _("Failed to update password: LDAP module not installed"))
            LDAPAuthBackend().update_user_password(self.username, curvalue,
                                                   raw_value)
        events.raiseEvent("PasswordUpdated", self, raw_value, self.pk is None)
Ejemplo n.º 18
0
def decode(value_bytes, encoding, append_to_error=""):
    """Try to decode the given string."""
    assert isinstance(value_bytes, six.binary_type),\
        "value_bytes should be of type %s" % six.binary_type.__name__
    if len(value_bytes) == 0:
        # short circuit for empty strings
        return ""
    try:
        value = value_bytes.decode(encoding)
    except UnicodeDecodeError:
        encoding = chardet.detect(value_bytes)
        try:
            value = value_bytes.decode(encoding["encoding"], "replace")
        except (TypeError, UnicodeDecodeError) as exc:
            six.raise_from(
                InternalError(
                    _("unable to determine encoding of string") +
                    append_to_error), exc)
    return value
Ejemplo n.º 19
0
def update_ldap_account(user, config):
    """Update existing account."""
    dn = config["ldap_sync_account_dn_template"] % {"user": user.username}
    conn = get_connection(config)
    if not check_if_dn_exists(conn, dn):
        create_ldap_account(user, dn, conn)
        return
    password = get_user_password(user, not user.is_active)
    ldif = [(ldap.MOD_REPLACE, "uid", force_bytes(user.username)),
            (ldap.MOD_REPLACE, "sn", force_bytes(user.last_name)),
            (ldap.MOD_REPLACE, "givenName", force_bytes(user.first_name)),
            (ldap.MOD_REPLACE, "cn", force_bytes(user.username)),
            (ldap.MOD_REPLACE, "displayName", force_bytes(user.fullname)),
            (ldap.MOD_REPLACE, "mail", force_bytes(user.email)),
            (ldap.MOD_REPLACE, "homePhone", force_bytes(user.phone_number)),
            (ldap.MOD_REPLACE, "userPassword", password)]
    try:
        conn.modify_s(dn, ldif)
    except ldap.LDAPError as e:
        raise InternalError(_("Failed to update LDAP account: {}").format(e))
Ejemplo n.º 20
0
def save_attachment(f):
    """Save a new attachment to the filesystem.

    The attachment is not saved using its own name to the
    filesystem. To avoid conflicts, a random name is generated and
    used instead.

    :param f: an uploaded file object (see Django's documentation)
    :return: the new random name
    """
    from tempfile import NamedTemporaryFile

    dstdir = os.path.join(settings.MEDIA_ROOT, "webmail")
    try:
        fp = NamedTemporaryFile(dir=dstdir, delete=False)
    except Exception as e:
        raise InternalError(str(e))
    for chunk in f.chunks():
        fp.write(chunk)
    fp.close()
    return fp.name
Ejemplo n.º 21
0
def create_ldap_account(user, dn, conn):
    """Create new account."""
    scheme, password = user.password.split("}")
    attrs = {
        "objectClass":
        [force_bytes("inetOrgPerson"),
         force_bytes("organizationalPerson")],
        "uid": [force_bytes(user.username)],
        "sn": [force_bytes(user.last_name)],
        "givenName": [force_bytes(user.first_name)],
        "cn": [force_bytes(user.username)],
        "displayName": [force_bytes(user.fullname)],
        "mail": [force_bytes(user.email),
                 force_bytes(user.secondary_email)],
        "homePhone": [force_bytes(user.phone_number)],
        "userPassword": [get_user_password(user)]
    }
    ldif = modlist.addModlist(attrs)
    try:
        conn.add_s(dn, ldif)
    except ldap.LDAPError as e:
        raise InternalError(_("Failed to create LDAP account: {}").format(e))
Ejemplo n.º 22
0
    def set_password(self, raw_value, curvalue=None):
        """Password update

        Update the current mailbox's password with the given clear
        value. This value is encrypted according to the defined method
        before it is saved.

        :param raw_value: the new password's value
        :param curvalue: the current password (for LDAP authentication)
        """
        ldap_sync_enable = param_tools.get_global_parameter("ldap_enable_sync")
        if self.is_local or ldap_sync_enable:
            self.password = self._crypt_password(raw_value)
        else:
            if not ldap_available:
                raise InternalError(
                    _("Failed to update password: LDAP module not installed"))
            LDAPAuthBackend().update_user_password(self.username, curvalue,
                                                   raw_value)
        signals.account_password_updated.send(sender=self.__class__,
                                              account=self,
                                              password=raw_value,
                                              created=self.pk is None)