Initial commit

This commit is contained in:
Julian Rother 2025-01-16 02:45:17 +01:00
commit 530fbab51c
Signed by: julian
GPG key ID: C19B924C0CD13341
9 changed files with 297 additions and 0 deletions

52
files/app/__init__.py Normal file
View file

@ -0,0 +1,52 @@
import json
from flask import Flask, request, Response, abort, render_template
from defusedxml import ElementTree as ET
app = Flask(__name__)
with open('/etc/mail-autodiscover.json') as f:
settings = json.load(f)
@app.route('/autodiscover/autodiscover.xml', methods=['GET', 'POST'])
@app.route('/Autodiscover/Autodiscover.xml', methods=['GET', 'POST'])
def outlook_autodiscover():
data = request.get_data()
try:
root = ET.fromstring(data)
schema = root.find('./{*}Request/{*}AcceptableResponseSchema').text
email = root.find('./{*}Request/{*}EMailAddress').text
email_username = email.rsplit('@', 1)[0]
email_domain = email.rsplit('@', 1)[-1]
except (SyntaxError, ValueError):
schema = 'http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006'
email = ''
email_username = ''
email_domain = ''
ctx = settings.copy()
ctx['email'] = email
ctx['email_username'] = email_username
ctx['email_domain'] = email_domain
return Response(
render_template('autodiscover.xml', **ctx),
content_type='application/xml',
)
@app.route('/mail/config-v1.1.xml')
def thunderbird_autoconfig():
ctx = settings.copy()
ctx['email'] = request.args.get('email', '')
return Response(
render_template('autoconfig.xml', **ctx),
content_type='application/xml',
)
@app.route('/email.mobileconfig')
def apple_mobileconfig():
ctx = settings.copy()
ctx['email'] = request.args['email']
return Response(
render_template('mobileconfig.xml', **ctx),
content_type='application/x-apple-aspen-config; charset=utf-8',
headers={'Content-Disposition': 'attachment; filename="email.mobileconfig"'},
)

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<clientConfig version="1.1">
<emailProvider id="{{domain}}">
<domain>{{domain}}</domain>
<displayName>{{info.name}} Email</displayName>
<displayShortName>%EMAILLOCALPART%</displayShortName>
{%- if imap.host %}
<incomingServer type="imap">
<hostname>{{imap.host}}</hostname>
<port>{{imap.port}}</port>
<socketType>{{imap.socket}}</socketType>
<authentication>password-cleartext</authentication>
<username>%EMAILADDRESS%</username>
</incomingServer>
{% endif -%}
{%- if smtp.host %}
<outgoingServer type="smtp">
<hostname>{{smtp.host}}</hostname>
<port>{{smtp.port}}</port>
<socketType>{{smtp.socket}}</socketType>
<authentication>password-cleartext</authentication>
<username>%EMAILADDRESS%</username>
</outgoingServer>
{% endif -%}
<documentation url="{{info.url}}">
<descr lang="en">Generic settings page</descr>
<descr lang="fr">Paramètres généraux</descr>
<descr lang="es">Configuraciones genéricas</descr>
<descr lang="de">Allgemeine Beschreibung der Einstellungen</descr>
<descr lang="ru">Страница общих настроек</descr>
</documentation>
</emailProvider>
</clientConfig>

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8" ?>
<Autodiscover
xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
<Response
xmlns="{{schema}}">
<User>
<DisplayName>{{info.name}}</DisplayName>
</User>
<Account>
<AccountType>email</AccountType>
<Action>settings</Action>
<ServiceHome>{{info.url}}</ServiceHome>
{%- if imap.host %}
<Protocol>
<Type>IMAP</Type>
<Server>{{imap.host}}</Server>
<Port>{{imap.port}}</Port>
{%- if email %}
<LoginName>{{email}}</LoginName>
{% endif -%}
<DomainRequired>on</DomainRequired>
<DomainName>{{domain}}</DomainName>
<SPA>on</SPA>
<SSL>{{ 'on' if imap.socket in ('SSL', 'STARTTLS') else 'off' }}</SSL>
<Encryption>{{ 'TLS' if imap.socket == 'STARTTLS' else imap.socket }}</Encryption>
<AuthRequired>on</AuthRequired>
</Protocol>
{% endif -%}
{%- if smtp.host %}
<Protocol>
<Type>SMTP</Type>
<Server>{{smtp.host}}</Server>
<Port>{{smtp.port}}</Port>
{%- if email %}
<LoginName>{{email}}</LoginName>
{% endif -%}
<DomainRequired>on</DomainRequired>
<DomainName>{{domain}}</DomainName>
<SPA>on</SPA>
<SSL>{{ 'on' if smtp.socket in ('SSL', 'STARTTLS') else 'off' }}</SSL>
<Encryption>{{ 'TLS' if imap.socket == 'STARTTLS' else imap.socket }}</Encryption>
<AuthRequired>on</AuthRequired>
</Protocol>
{% endif -%}
</Account>
</Response>
</Autodiscover>

View file

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>HasRemovalPasscode</key>
<false/>
<key>PayloadContent</key>
<array>
{% if imap.host %}
<dict>
<key>EmailAccountDescription</key>
<string>{{email}}</string>
<key>EmailAccountName</key>
<string>{{email}}</string>
<key>EmailAccountType</key>
<string>{% if imap.host %}EmailTypeIMAP{% else %}EmailTypePOP{% endif %}</string>
<key>EmailAddress</key>
<string>{{email}}</string>
<key>IncomingMailServerAuthentication</key>
<string>EmailAuthPassword</string>
<key>IncomingMailServerHostName</key>
<string>{{imap.host}}</string>
<key>IncomingMailServerPortNumber</key>
<integer>{{imap.port}}</integer>
<key>IncomingMailServerUseSSL</key>
<{{ 'true' if imap.socket in ['SSL', 'STARTTLS'] else 'false' }}/>
<key>IncomingMailServerUsername</key>
<string>{{email}}</string>
<key>OutgoingPasswordSameAsIncomingPassword</key>
<true/>
<key>OutgoingMailServerAuthentication</key>
<string>EmailAuthPassword</string>
<key>OutgoingMailServerHostName</key>
<string>{{smtp.host}}</string>
<key>OutgoingMailServerPortNumber</key>
<integer>{{smtp.port}}</integer>
<key>OutgoingMailServerUseSSL</key>
<{{ 'true' if smtp.socket in ['SSL', 'STARTTLS'] else 'false' }}/>
<key>OutgoingMailServerUsername</key>
<string>{{email}}</string>
<key>SMIMEEnabled</key>
<false/>
<key>SMIMEEnablePerMessageSwitch</key>
<false/>
<key>SMIMEEnableEncryptionPerMessageSwitch</key>
<false/>
<key>disableMailRecentsSyncing</key>
<false/>
<key>PayloadDescription</key>
<string>{{info.name}} Email</string>
<key>PayloadDisplayName</key>
<string>{{email}}</string>
<key>PayloadIdentifier</key>
<string>{{mobile.identifier}}.com.apple.mail.managed.{{mobile.mail.uuid}}</string>
<key>PayloadType</key>
<string>com.apple.mail.managed</string>
<key>PayloadUUID</key>
<string>{{mobile.mail.uuid}}</string>
<key>PayloadVersion</key>
<real>1</real>
</dict>
{% endif %}
</array>
<key>PayloadDescription</key>
<string>{{info.name}}</string>
<key>PayloadDisplayName</key>
<string>{{email}}</string>
<key>PayloadIdentifier</key>
<string>{{mobile.identifier}}</string>
<key>PayloadOrganization</key>
<string>{{domain}}</string>
<key>PayloadRemovalDisallowed</key>
<false/>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>{{mobile.uuid}}</string>
<key>PayloadVersion</key>
<integer>2</integer>
</dict>
</plist>

View file

@ -0,0 +1,20 @@
[Unit]
Description=Mail Autodiscover Service
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
DynamicUser=true
WorkingDirectory=/usr/local/lib/mail-autodiscover
Environment="PYTHONUNBUFFERED=1"
ExecStart=/usr/bin/gunicorn --workers=2 --log-level=info -b 127.0.0.1:8749 app:app
Restart=on-failure
RestartSec=30
PrivateTmp=true
ProtectSystem=strict
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target