Merge branch 'master' into feat-fuzzyhashes
						commit
						cec5c1b16b
					
				| @ -0,0 +1,3 @@ | ||||
| __all__ = [ | ||||
|     'auth', 'postfix', 'dovecot', 'fetch' | ||||
| ] | ||||
| @ -0,0 +1,40 @@ | ||||
| from mailu import db, models | ||||
| from mailu.internal import internal | ||||
| 
 | ||||
| import flask | ||||
| 
 | ||||
| 
 | ||||
| @internal.route("/dovecot/passdb/<user_email>") | ||||
| def dovecot_passdb_dict(user_email): | ||||
|     user = models.User.query.get(user_email) or flask.abort(404) | ||||
|     return flask.jsonify({ | ||||
|         "password": user.password, | ||||
|     }) | ||||
| 
 | ||||
| 
 | ||||
| @internal.route("/dovecot/userdb/<user_email>") | ||||
| def dovecot_userdb_dict(user_email): | ||||
|     user = models.User.query.get(user_email) or flask.abort(404) | ||||
|     return flask.jsonify({ | ||||
|         "quota_rule": "*:bytes={}".format(user.quota_bytes) | ||||
|     }) | ||||
| 
 | ||||
| 
 | ||||
| @internal.route("/dovecot/quota/<ns>/<user_email>", methods=["POST"]) | ||||
| def dovecot_quota(ns, user_email): | ||||
|     user = models.User.query.get(user_email) or flask.abort(404) | ||||
|     if ns == "storage": | ||||
|         user.quota_bytes_used = flask.request.get_json() | ||||
|         db.session.commit() | ||||
|     return flask.jsonify(None) | ||||
| 
 | ||||
| 
 | ||||
| @internal.route("/dovecot/sieve/name/<script>/<user_email>") | ||||
| def dovecot_sieve_name(script, user_email): | ||||
|     return flask.jsonify(script) | ||||
| 
 | ||||
| 
 | ||||
| @internal.route("/dovecot/sieve/data/default/<user_email>") | ||||
| def dovecot_sieve_data(user_email): | ||||
|     user = models.User.query.get(user_email) or flask.abort(404) | ||||
|     return flask.jsonify(flask.render_template("default.sieve", user=user)) | ||||
| @ -0,0 +1,32 @@ | ||||
| from mailu import db, models | ||||
| from mailu.internal import internal | ||||
| 
 | ||||
| import flask | ||||
| import datetime | ||||
| 
 | ||||
| 
 | ||||
| @internal.route("/fetch") | ||||
| def fetch_list(): | ||||
|     return flask.jsonify([ | ||||
|         { | ||||
|             "id": fetch.id, | ||||
|             "tls": fetch.tls, | ||||
|             "keep": fetch.keep, | ||||
|             "user_email": fetch.user_email, | ||||
|             "protocol": fetch.protocol, | ||||
|             "host": fetch.host, | ||||
|             "port": fetch.port, | ||||
|             "username": fetch.username, | ||||
|             "password": fetch.password | ||||
|         } for fetch in models.Fetch.query.all() | ||||
|     ]) | ||||
| 
 | ||||
| 
 | ||||
| @internal.route("/fetch/<fetch_id>", methods=["POST"]) | ||||
| def fetch_done(fetch_id): | ||||
|     fetch = models.Fetch.query.get(fetch_id) or flask.abort(404) | ||||
|     fetch.last_check = datetime.datetime.now() | ||||
|     fetch.error_message = str(flask.request.get_json()) | ||||
|     db.session.add(fetch) | ||||
|     db.session.commit() | ||||
|     return "" | ||||
| @ -0,0 +1,54 @@ | ||||
| from mailu import db, models | ||||
| from mailu.internal import internal | ||||
| 
 | ||||
| import flask | ||||
| 
 | ||||
| 
 | ||||
| @internal.route("/postfix/domain/<domain_name>") | ||||
| def postfix_mailbox_domain(domain_name): | ||||
|     domain = models.Domain.query.get(domain_name) or flask.abort(404) | ||||
|     return flask.jsonify(domain.name) | ||||
| 
 | ||||
| 
 | ||||
| @internal.route("/postfix/mailbox/<email>") | ||||
| def postfix_mailbox_map(email): | ||||
|     user = models.User.query.get(email) or flask.abort(404) | ||||
|     return flask.jsonify(user.email) | ||||
| 
 | ||||
| 
 | ||||
| @internal.route("/postfix/alias/<alias>") | ||||
| def postfix_alias_map(alias): | ||||
|     localpart, domain = alias.split('@', 1) if '@' in alias else (None, alias) | ||||
|     alternative = models.Alternative.query.get(domain) | ||||
|     if alternative: | ||||
|         domain = alternative.domain_name | ||||
|     email = '{}@{}'.format(localpart, domain) | ||||
|     if localpart is None: | ||||
|         return flask.jsonify(domain) | ||||
|     else: | ||||
|         alias_obj = models.Alias.resolve(localpart, domain) | ||||
|         if alias_obj: | ||||
|             return flask.jsonify(",".join(alias_obj.destination)) | ||||
|         user_obj = models.User.query.get(email) | ||||
|         if user_obj: | ||||
|             return flask.jsonify(user_obj.destination) | ||||
|         return flask.abort(404) | ||||
| 
 | ||||
| 
 | ||||
| @internal.route("/postfix/transport/<email>") | ||||
| def postfix_transport(email): | ||||
|     localpart, domain = email.split('@', 1) if '@' in email else (None, email) | ||||
|     relay = models.Relay.query.get(domain) or flask.abort(404) | ||||
|     return flask.jsonify("smtp:[{}]".format(relay.smtp)) | ||||
| 
 | ||||
| 
 | ||||
| @internal.route("/postfix/sender/<sender>") | ||||
| def postfix_sender(sender): | ||||
|     """ Simply reject any sender that pretends to be from a local domain | ||||
|     """ | ||||
|     localpart, domain_name = sender.split('@', 1) if '@' in sender else (None, sender) | ||||
|     domain = models.Domain.query.get(domain_name) | ||||
|     alternative = models.Alternative.query.get(domain_name) | ||||
|     if domain or alternative: | ||||
|         return flask.jsonify("REJECT") | ||||
|     return flask.abort(404) | ||||
| @ -0,0 +1,28 @@ | ||||
| """ Add a column for used quota | ||||
| 
 | ||||
| Revision ID: 25fd6c7bcb4a | ||||
| Revises: 049fed905da7 | ||||
| Create Date: 2018-07-25 21:56:09.729153 | ||||
| 
 | ||||
| """ | ||||
| 
 | ||||
| # revision identifiers, used by Alembic. | ||||
| revision = '25fd6c7bcb4a' | ||||
| down_revision = '049fed905da7' | ||||
| 
 | ||||
| from alembic import op | ||||
| import sqlalchemy as sa | ||||
| 
 | ||||
| 
 | ||||
| from alembic import op | ||||
| import sqlalchemy as sa | ||||
| 
 | ||||
| 
 | ||||
| def upgrade(): | ||||
|     with op.batch_alter_table('user') as batch: | ||||
|         batch.add_column(sa.Column('quota_bytes_used', sa.Integer(), nullable=False, server_default='0')) | ||||
| 
 | ||||
| 
 | ||||
| def downgrade(): | ||||
|     with op.batch_alter_table('user') as batch: | ||||
|         batch.drop_column('user', 'quota_bytes_used') | ||||
| @ -0,0 +1,5 @@ | ||||
| uri = proxy:/tmp/podop.socket:auth | ||||
| iterate_disable = yes | ||||
| default_pass_scheme = plain | ||||
| password_key = passdb/%u | ||||
| user_key = userdb/%u | ||||
| @ -1,18 +0,0 @@ | ||||
| driver = sqlite | ||||
| connect = /data/main.db | ||||
| 
 | ||||
| # Return the user hashed password | ||||
| password_query = \ | ||||
|  SELECT NULL as password, 'Y' as nopassword, '{% if POD_ADDRESS_RANGE %}{{ POD_ADDRESS_RANGE }}{% else %}{{ FRONT_ADDRESS }}{% if WEBMAIL_ADDRESS %},{{ WEBMAIL_ADDRESS }}{% endif %}{% endif %}' as allow_nets \ | ||||
|    FROM user \ | ||||
|   WHERE user.email = '%u' | ||||
| 
 | ||||
| # Mostly get the user quota | ||||
| user_query = \ | ||||
|  SELECT '*:bytes=' || user.quota_bytes AS quota_rule \ | ||||
|    FROM user \ | ||||
|   WHERE user.email = '%u' | ||||
| 
 | ||||
| # For using doveadm -A: | ||||
| iterate_query = \ | ||||
|  SELECT user.email AS user FROM user | ||||
| @ -1,43 +0,0 @@ | ||||
| connect = /data/main.db | ||||
| 
 | ||||
| map { | ||||
|   pattern = priv/spam_enabled | ||||
|   table = user | ||||
|   username_field = email | ||||
|   value_field = spam_enabled | ||||
| } | ||||
| 
 | ||||
| map { | ||||
|   pattern = priv/spam_threshold | ||||
|   table = user | ||||
|   username_field = email | ||||
|   value_field = spam_threshold | ||||
| } | ||||
| 
 | ||||
| map { | ||||
|   pattern = priv/reply_enabled | ||||
|   table = user | ||||
|   username_field = email | ||||
|   value_field = reply_enabled | ||||
| } | ||||
| 
 | ||||
| map { | ||||
|   pattern = priv/reply_subject | ||||
|   table = user | ||||
|   username_field = email | ||||
|   value_field = reply_subject | ||||
| } | ||||
| 
 | ||||
| map { | ||||
|   pattern = priv/reply_body | ||||
|   table = user | ||||
|   username_field = email | ||||
|   value_field = reply_body | ||||
| } | ||||
| 
 | ||||
| map { | ||||
|   pattern = priv/reply_enddate | ||||
|   table = user | ||||
|   username_field = email | ||||
|   value_field = reply_enddate | ||||
| } | ||||
| @ -1,5 +1,5 @@ | ||||
| # This is an idle image to dynamically replace any component if disabled. | ||||
| 
 | ||||
| FROM alpine | ||||
| FROM alpine:3.8 | ||||
| 
 | ||||
| CMD sleep 1000000d | ||||
|  | ||||
| @ -1,5 +0,0 @@ | ||||
| dbpath = /data/main.db | ||||
| query = | ||||
|   SELECT 'REJECT' FROM domain WHERE name='%s' | ||||
|   UNION | ||||
|   SELECT 'REJECT' FROM alternative WHERE name='%s' | ||||
| @ -1,3 +0,0 @@ | ||||
| dbpath = /data/main.db | ||||
| query = | ||||
|   SELECT 'smtp:['||smtp||']' FROM relay WHERE name='%s' | ||||
| @ -1,23 +0,0 @@ | ||||
| dbpath = /data/main.db | ||||
| query = | ||||
|   SELECT destination | ||||
|    FROM | ||||
|      (SELECT destination, email, wildcard, localpart, localpart||'@'||alternative.name AS alt_email FROM alias LEFT JOIN alternative ON alias.domain_name = alternative.domain_name | ||||
|       UNION | ||||
|       SELECT (CASE WHEN forward_enabled=1 THEN (CASE WHEN forward_keep=1 THEN email||',' ELSE '' END)||forward_destination ELSE email END) AS destination, email, 0 as wildcard, localpart, localpart||'@'||alternative.name as alt_email FROM user LEFT JOIN alternative ON user.domain_name = alternative.domain_name | ||||
|       UNION | ||||
|       SELECT '@'||domain_name as destination, '@'||name as email, 0 as wildcard, '' as localpart, NULL AS alt_email FROM alternative) | ||||
|    WHERE | ||||
|      ( | ||||
|       wildcard = 0 | ||||
|       AND | ||||
|       (email = '%s' OR alt_email = '%s') | ||||
|      ) OR ( | ||||
|       wildcard = 1 | ||||
|       AND | ||||
|       '%s' LIKE email | ||||
|      ) | ||||
|    ORDER BY | ||||
|      wildcard ASC, | ||||
|      length(localpart) DESC | ||||
|    LIMIT 1 | ||||
| @ -1,5 +0,0 @@ | ||||
| dbpath = /data/main.db | ||||
| query = | ||||
|   SELECT name FROM domain WHERE name='%s' | ||||
|   UNION | ||||
|   SELECT name FROM alternative WHERE name='%s' | ||||
| @ -1,7 +1,9 @@ | ||||
| FROM python:alpine | ||||
| FROM python:3-alpine | ||||
| 
 | ||||
| RUN apk add --no-cache fetchmail ca-certificates | ||||
| RUN apk add --no-cache fetchmail ca-certificates \ | ||||
|  && pip install requests | ||||
| 
 | ||||
| COPY fetchmail.py /fetchmail.py | ||||
| USER fetchmail | ||||
| 
 | ||||
| CMD ["/fetchmail.py"] | ||||
|  | ||||
| @ -0,0 +1,17 @@ | ||||
| import smtplib | ||||
| import sys | ||||
| from email import mime | ||||
| 
 | ||||
| from email.mime.image import MIMEImage | ||||
| from email.mime.multipart import MIMEMultipart | ||||
| 
 | ||||
| msg = mime.multipart.MIMEMultipart() | ||||
| msg['Subject'] = 'Test email' | ||||
| msg['From'] = sys.argv[1] | ||||
| msg['To'] = sys.argv[2] | ||||
| msg.preamble = 'Test email' | ||||
| 
 | ||||
| s = smtplib.SMTP('localhost') | ||||
| s.set_debuglevel(1) | ||||
| s.send_message(msg) | ||||
| s.quit() | ||||
					Loading…
					
					
				
		Reference in New Issue
	
	 ofthesun9
						ofthesun9