1
0
mirror of https://github.com/Mailu/Mailu.git synced 2024-12-14 10:53:30 +02:00
Mailu/core/admin/mailu/ui/forms.py

210 lines
9.3 KiB
Python
Raw Normal View History

2016-03-19 21:37:48 +02:00
from wtforms import validators, fields, widgets
from wtforms_components import fields as fields_
2016-10-02 14:37:06 +02:00
from flask_babel import lazy_gettext as _
2016-08-13 20:51:54 +02:00
import flask_login
import flask_wtf
import re
import ipaddress
LOCALPART_REGEX = "^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*$"
class DestinationField(fields.SelectMultipleField):
""" Allow for multiple emails selection from current user choices and
additional email addresses.
"""
validator = re.compile(r'^.+@([^.@][^@]+)$', re.IGNORECASE)
def iter_choices(self):
managed = [
str(email)
for email in flask_login.current_user.get_managed_emails()
]
for email in managed:
selected = self.data is not None and self.coerce(email) in self.data
yield (email, email, selected)
for email in self.data or ():
if email not in managed:
yield (email, email, True)
def pre_validate(self, form):
for item in self.data:
if not self.validator.match(item):
2016-10-02 14:37:06 +02:00
raise validators.ValidationError(_('Invalid email address.'))
2016-03-19 21:37:48 +02:00
2018-12-28 22:03:57 +02:00
class MultipleEmailAddressesVerify(object):
def __init__(self,message=_('Invalid email address.')):
self.message = message
def __call__(self, form, field):
pattern = re.compile(r'^([_a-z0-9\-\+]+)(\.[_a-z0-9\-\+]+)*@([a-z0-9\-]{1,}\.)*([a-z]{1,})(,([_a-z0-9\-\+]+)(\.[_a-z0-9\-\+]+)*@([a-z0-9\-]{1,}\.)*([a-z]{2,}))*$')
2018-12-28 22:03:57 +02:00
if not pattern.match(field.data.replace(" ", "")):
raise validators.ValidationError(self.message)
2016-03-19 21:37:48 +02:00
2022-11-13 18:15:50 +02:00
class MultipleFoldersVerify(object):
2022-11-21 11:38:44 +02:00
""" Ensure that we have CSV formated data """
2022-11-13 18:15:50 +02:00
def __init__(self,message=_('Invalid list of folders.')):
self.message = message
def __call__(self, form, field):
pattern = re.compile(r'^[^,]+(,[^,]+)*$')
2022-11-13 18:15:50 +02:00
if not pattern.match(field.data.replace(" ", "")):
raise validators.ValidationError(self.message)
2016-10-02 14:53:01 +02:00
class ConfirmationForm(flask_wtf.FlaskForm):
2016-10-02 14:37:06 +02:00
submit = fields.SubmitField(_('Confirm'))
class DomainForm(flask_wtf.FlaskForm):
2016-10-02 14:37:06 +02:00
name = fields.StringField(_('Domain name'), [validators.DataRequired()])
max_users = fields_.IntegerField(_('Maximum user count'), [validators.NumberRange(min=-1)], default=10)
max_aliases = fields_.IntegerField(_('Maximum alias count'), [validators.NumberRange(min=-1)], default=10)
max_quota_bytes = fields_.IntegerSliderField(_('Maximum user quota'), default=0)
2017-12-03 13:01:25 +02:00
signup_enabled = fields.BooleanField(_('Enable sign-up'), default=False)
2016-10-02 14:37:06 +02:00
comment = fields.StringField(_('Comment'))
submit = fields.SubmitField(_('Save'))
2016-03-19 21:37:48 +02:00
2018-04-18 20:31:32 +02:00
class DomainSignupForm(flask_wtf.FlaskForm):
name = fields.StringField(_('Domain name'), [validators.DataRequired()])
localpart = fields.StringField(_('Initial admin'), [validators.DataRequired()])
pw = fields.PasswordField(_('Admin password'), [validators.DataRequired()])
pw2 = fields.PasswordField(_('Confirm password'), [validators.EqualTo('pw')])
2022-11-04 14:35:13 +02:00
pwned = fields.HiddenField(label='', default=-1)
2018-04-18 20:31:32 +02:00
captcha = flask_wtf.RecaptchaField()
submit = fields.SubmitField(_('Create'))
class AlternativeForm(flask_wtf.FlaskForm):
name = fields.StringField(_('Alternative name'), [validators.DataRequired()])
submit = fields.SubmitField(_('Save'))
class RelayForm(flask_wtf.FlaskForm):
name = fields.StringField(_('Relayed domain name'), [validators.DataRequired()])
smtp = fields.StringField(_('Remote host'))
comment = fields.StringField(_('Comment'))
submit = fields.SubmitField(_('Save'))
class UserForm(flask_wtf.FlaskForm):
localpart = fields.StringField(_('E-mail'), [validators.DataRequired(), validators.Regexp(LOCALPART_REGEX)])
2019-01-09 13:03:47 +02:00
pw = fields.PasswordField(_('Password'))
2016-10-02 14:37:06 +02:00
pw2 = fields.PasswordField(_('Confirm password'), [validators.EqualTo('pw')])
2022-11-04 14:35:13 +02:00
pwned = fields.HiddenField(label='', default=-1)
AdminLTE3 optimizations & compression and caching - fixed copy of qemu-arm-static for alpine - added 'set -eu' safeguard - silenced npm update notification - added color to webpack call - changed Admin-LTE default blue (core/admin/Dockerfile) - AdminLTE 3 style tweaks (core/admin/assets/app.css) (core/admin/mailu/ui/templates/base.html) (core/admin/mailu/ui/templates/sidebar.html) - localized datatables (core/admin/Dockerfile) (core/admin/assets/app.js) (core/admin/package.json) - moved external javascript code to vendor.js (core/admin/assets/app.js) (core/admin/assets/vendor.js) (core/admin/webpack.config.js) - added mailu logo (core/admin/assets/app.js) (core/admin/assets/app.css) (core/admin/assets/mailu.png) - moved all inline javascript to app.js (core/admin/assets/app.js) (core/admin/mailu/ui/templates/domain/create.html) (core/admin/mailu/ui/templates/user/create.html) - added iframe display of rspamd page (core/admin/assets/app.js) (core/admin/mailu/ui/views/base.py) (core/admin/mailu/ui/templates/sidebar.html) (core/admin/mailu/ui/templates/antispam.html) - updated language-selector to display full language names and use post (core/admin/assets/app.js) (core/admin/mailu/__init__.py) (core/admin/mailu/utils.py) (core/admin/mailu/ui/views/languages.py) - added fieldset to group and en/disable input fields (core/admin/assets/app.js) (core/admin/mailu/ui/templates/macros.html) (core/admin/mailu/ui/templates/user/settings.html) (core/admin/mailu/ui/templates/user/reply.html) - added clipboard copy buttons (core/admin/assets/app.js) (core/admin/assets/vendor.js) (core/admin/mailu/ui/templates/macros.html) (core/admin/mailu/ui/templates/domain/details.html) - cleaned external javascript imports (core/admin/assets/vendor.js) - pre-split first hostname for further use (core/admin/mailu/__init__.py) (core/admin/mailu/models.py) (core/admin/mailu/ui/templates/client.html) (core/admin/mailu/ui/templates/domain/signup.html) - cache dns_* properties of domain object (immutable during runtime) (core/admin/mailu/models.py) (core/admin/mailu/ui/templates/domain/details.html) - fixed and splitted dns_dkim property of domain object (space missing) - added autoconfig and tlsa properties to domain object (core/admin/mailu/models.py) - suppressed extra vertical spacing in jinja2 templates - improved accessibility for screen reader (core/admin/mailu/ui/templates/**.html) - deleted unused/broken /user/forward route (core/admin/mailu/ui/templates/user/forward.html) (core/admin/mailu/ui/views/users.py) - updated gunicorn to 20.1.0 to get rid of buffering error at startup (core/admin/requirements-prod.txt) - switched webpack to production mode (core/admin/webpack.config.js) - added css and javascript minimization - added pre-compression of assets (gzip) (core/admin/webpack.config.js) (core/admin/package.json) - removed obsolte dependencies - switched from node-sass to dart-sass (core/admin/package.json) - changed startup cleaning message from error to info (core/admin/mailu/utils.py) - move client config to "my account" section when logged in (core/admin/mailu/ui/templates/sidebar.html)
2021-09-02 22:49:36 +02:00
quota_bytes = fields_.IntegerSliderField(_('Quota'), default=10**9)
2016-10-02 14:37:06 +02:00
enable_imap = fields.BooleanField(_('Allow IMAP access'), default=True)
enable_pop = fields.BooleanField(_('Allow POP3 access'), default=True)
allow_spoofing = fields.BooleanField(_('Allow the user to spoof the sender (send email as anyone)'), default=False)
2018-12-30 21:29:41 +02:00
displayed_name = fields.StringField(_('Displayed name'))
2016-10-02 14:37:06 +02:00
comment = fields.StringField(_('Comment'))
2018-04-15 11:35:37 +02:00
enabled = fields.BooleanField(_('Enabled'), default=True)
change_pw_next_login = fields.BooleanField(_('Force password change at next login'), default=True)
2016-10-02 14:37:06 +02:00
submit = fields.SubmitField(_('Save'))
2016-03-19 21:37:48 +02:00
2017-12-03 13:01:25 +02:00
class UserSignupForm(flask_wtf.FlaskForm):
localpart = fields.StringField(_('Email address'), [validators.DataRequired(), validators.Regexp(LOCALPART_REGEX)])
2017-12-03 13:01:25 +02:00
pw = fields.PasswordField(_('Password'), [validators.DataRequired()])
pw2 = fields.PasswordField(_('Confirm password'), [validators.EqualTo('pw')])
2022-11-04 14:35:13 +02:00
pwned = fields.HiddenField(label='', default=-1)
2017-12-03 13:01:25 +02:00
submit = fields.SubmitField(_('Sign up'))
class UserSignupFormCaptcha(UserSignupForm):
captcha = flask_wtf.RecaptchaField()
2017-12-03 13:01:25 +02:00
class UserSettingsForm(flask_wtf.FlaskForm):
2016-10-02 14:37:06 +02:00
displayed_name = fields.StringField(_('Displayed name'))
spam_enabled = fields.BooleanField(_('Enable spam filter'))
2022-03-11 15:58:50 +02:00
spam_mark_as_read = fields.BooleanField(_('Enable marking spam mails as read'))
spam_threshold = fields_.IntegerSliderField(_('Spam filter tolerance'))
forward_enabled = fields.BooleanField(_('Enable forwarding'))
forward_keep = fields.BooleanField(_('Keep a copy of the emails'))
2018-12-28 22:03:57 +02:00
forward_destination = fields.StringField(_('Destination'), [validators.Optional(), MultipleEmailAddressesVerify()])
2016-10-02 14:37:06 +02:00
submit = fields.SubmitField(_('Save settings'))
2016-03-20 12:09:06 +02:00
class UserPasswordForm(flask_wtf.FlaskForm):
2016-10-02 14:37:06 +02:00
pw = fields.PasswordField(_('Password'), [validators.DataRequired()])
pw2 = fields.PasswordField(_('Password check'), [validators.DataRequired()])
2022-11-04 14:35:13 +02:00
pwned = fields.HiddenField(label='', default=-1)
2016-10-02 14:37:06 +02:00
submit = fields.SubmitField(_('Update password'))
2016-03-19 21:37:48 +02:00
class UserPasswordChangeForm(flask_wtf.FlaskForm):
current_pw = fields.PasswordField(_('Current password'), [validators.DataRequired()])
pw = fields.PasswordField(_('Password'), [validators.DataRequired()])
pw2 = fields.PasswordField(_('Password check'), [validators.DataRequired()])
pwned = fields.HiddenField(label='', default=-1)
submit = fields.SubmitField(_('Update password'))
2016-03-19 21:37:48 +02:00
class UserReplyForm(flask_wtf.FlaskForm):
2016-10-02 14:37:06 +02:00
reply_enabled = fields.BooleanField(_('Enable automatic reply'))
reply_subject = fields.StringField(_('Reply subject'))
reply_body = fields.StringField(_('Reply body'),
widget=widgets.TextArea())
2022-11-02 18:52:38 +02:00
reply_startdate = fields.DateField(_('Start of vacation'))
reply_enddate = fields.DateField(_('End of vacation'))
2016-10-02 14:37:06 +02:00
submit = fields.SubmitField(_('Update'))
class TokenForm(flask_wtf.FlaskForm):
2017-10-29 16:39:01 +02:00
displayed_password = fields.StringField(
_('Your token (write it down, as it will never be displayed again)')
)
2017-10-29 16:39:01 +02:00
raw_password = fields.HiddenField([validators.DataRequired()])
comment = fields.StringField(_('Comment'))
ip = fields.StringField(
_('Authorized IP'), [validators.Optional()]
)
submit = fields.SubmitField(_('Save'))
def validate_ip(form, field):
if not field.data:
return True
try:
for candidate in field.data.replace(' ','').split(','):
ipaddress.ip_network(candidate, False)
except:
raise validators.ValidationError('Not a valid list of CIDRs')
class AliasForm(flask_wtf.FlaskForm):
localpart = fields.StringField(_('Alias'), [validators.DataRequired(), validators.Regexp(LOCALPART_REGEX)])
2016-08-15 21:01:53 +02:00
wildcard = fields.BooleanField(
2016-10-02 14:37:06 +02:00
_('Use SQL LIKE Syntax (e.g. for catch-all aliases)'))
destination = DestinationField(_('Destination'))
comment = fields.StringField(_('Comment'))
submit = fields.SubmitField(_('Save'))
2016-04-24 19:17:40 +02:00
class AdminForm(flask_wtf.FlaskForm):
2016-10-02 14:37:06 +02:00
admin = fields.SelectField(_('Admin email'), choices=[])
submit = fields.SubmitField(_('Submit'))
2016-04-24 19:17:40 +02:00
class ManagerForm(flask_wtf.FlaskForm):
2016-10-02 14:37:06 +02:00
manager = fields.SelectField(_('Manager email'))
submit = fields.SubmitField(_('Submit'))
2016-04-28 20:07:38 +02:00
class FetchForm(flask_wtf.FlaskForm):
2016-10-02 14:37:06 +02:00
protocol = fields.SelectField(_('Protocol'), choices=[
2016-04-28 20:07:38 +02:00
('imap', 'IMAP'), ('pop3', 'POP3')
])
host = fields.StringField(_('Hostname or IP'), [validators.DataRequired()])
2022-11-13 18:15:50 +02:00
port = fields.IntegerField(_('TCP port'), [validators.DataRequired(), validators.NumberRange(min=0, max=65535)], default=993)
tls = fields.BooleanField(_('Enable TLS'), default=True)
username = fields.StringField(_('Username'), [validators.DataRequired()])
password = fields.PasswordField(_('Password'))
2017-02-02 23:45:43 +02:00
keep = fields.BooleanField(_('Keep emails on the server'))
2022-11-13 18:15:50 +02:00
scan = fields.BooleanField(_('Rescan emails locally'))
folders = fields.StringField(_('Folders to fetch on the server'), [validators.Optional(), MultipleFoldersVerify()], default='INBOX,Junk')
2016-10-02 14:37:06 +02:00
submit = fields.SubmitField(_('Submit'))
2016-11-10 11:48:37 +02:00
class AnnouncementForm(flask_wtf.FlaskForm):
announcement_subject = fields.StringField(_('Announcement subject'),
[validators.DataRequired()])
announcement_body = fields.StringField(_('Announcement body'),
[validators.DataRequired()], widget=widgets.TextArea())
submit = fields.SubmitField(_('Send'))