Fix email logo: resize/compress to small JPEG, make path configurable in settings, add Pillow
This commit is contained in:
parent
48db5c5461
commit
918eaa682c
6 changed files with 80206 additions and 10 deletions
46
app.py
46
app.py
|
|
@ -300,21 +300,45 @@ def send_email(to, subject, body, attachments=None, inline_images=None):
|
||||||
|
|
||||||
|
|
||||||
def build_signature_images():
|
def build_signature_images():
|
||||||
"""Return inline image tuple list for the Dionysis Media logo if present."""
|
"""
|
||||||
logo_path = Path('/mnt/Storage/DM-Logo.png')
|
Return inline image tuple list for the Dionysis Media logo if present.
|
||||||
if logo_path.exists():
|
The logo path is configurable via /admin/settings. A downscaled, compressed
|
||||||
return [(str(logo_path), 'dm-logo')]
|
email-sized JPEG copy is generated in the upload folder so attachments stay small.
|
||||||
return []
|
:return: list of (path, cid) tuples. Empty if no logo is configured or not found.
|
||||||
|
"""
|
||||||
|
cfg = load_booth_settings()
|
||||||
|
logo_path = cfg.get('logo_path') or '/mnt/Storage/DM-Logo.png'
|
||||||
|
logo_file = Path(logo_path)
|
||||||
|
if not logo_file.exists():
|
||||||
|
return []
|
||||||
|
# Cache a small email-friendly JPEG inside the upload folder.
|
||||||
|
cache_dir = Path(current_app.config['UPLOAD_FOLDER'])
|
||||||
|
cache_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
email_logo = cache_dir / 'dm-logo.email.jpg'
|
||||||
|
try:
|
||||||
|
from PIL import Image
|
||||||
|
with Image.open(logo_file) as im:
|
||||||
|
im.thumbnail((600, 600))
|
||||||
|
if im.mode in ('RGBA', 'LA', 'P'):
|
||||||
|
# Composite transparent images onto a white background for JPEG.
|
||||||
|
background = Image.new('RGB', im.size, (255, 255, 255))
|
||||||
|
if im.mode == 'P':
|
||||||
|
im = im.convert('RGBA')
|
||||||
|
background.paste(im, mask=im.split()[-1] if im.mode == 'RGBA' else None)
|
||||||
|
im = background
|
||||||
|
else:
|
||||||
|
im = im.convert('RGB')
|
||||||
|
im.save(email_logo, format='JPEG', optimize=True, quality=85)
|
||||||
|
except Exception:
|
||||||
|
# If resize fails, fall back to the original file.
|
||||||
|
return [(str(logo_file), 'dm-logo')]
|
||||||
|
return [(str(email_logo), 'dm-logo')]
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Public customer routes
|
# Public customer routes
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
@app.route('/')
|
|
||||||
def index():
|
|
||||||
"""Root route: redirect customers straight to the request form."""
|
|
||||||
return redirect(url_for('request_form'))
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/request', methods=['GET', 'POST'])
|
@app.route('/request', methods=['GET', 'POST'])
|
||||||
@limiter.limit("5 per minute")
|
@limiter.limit("5 per minute")
|
||||||
|
|
@ -688,6 +712,7 @@ def admin_settings():
|
||||||
'smtp_user': runtime_settings.get('smtp_user', current_app.config['SMTP_USER']),
|
'smtp_user': runtime_settings.get('smtp_user', current_app.config['SMTP_USER']),
|
||||||
'smtp_from': runtime_settings.get('smtp_from', current_app.config['SMTP_FROM']),
|
'smtp_from': runtime_settings.get('smtp_from', current_app.config['SMTP_FROM']),
|
||||||
'smtp_pass_set': bool(runtime_settings.get('smtp_pass', '')),
|
'smtp_pass_set': bool(runtime_settings.get('smtp_pass', '')),
|
||||||
|
'logo_path': runtime_settings.get('logo_path', '/mnt/Storage/DM-Logo.png'),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Compute upload folder stats.
|
# Compute upload folder stats.
|
||||||
|
|
@ -798,6 +823,7 @@ def admin_settings():
|
||||||
cfg['smtp_port'] = request.form.get('smtp_port', '').strip() or None
|
cfg['smtp_port'] = request.form.get('smtp_port', '').strip() or None
|
||||||
cfg['smtp_user'] = request.form.get('smtp_user', '').strip() or None
|
cfg['smtp_user'] = request.form.get('smtp_user', '').strip() or None
|
||||||
cfg['smtp_from'] = request.form.get('smtp_from', '').strip() or None
|
cfg['smtp_from'] = request.form.get('smtp_from', '').strip() or None
|
||||||
|
cfg['logo_path'] = request.form.get('logo_path', '').strip() or None
|
||||||
new_pass = request.form.get('smtp_pass', '').strip()
|
new_pass = request.form.get('smtp_pass', '').strip()
|
||||||
# Only overwrite the stored password if a new value was provided.
|
# Only overwrite the stored password if a new value was provided.
|
||||||
if new_pass:
|
if new_pass:
|
||||||
|
|
|
||||||
3
booth_settings.json
Normal file
3
booth_settings.json
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"logo_path": "/mnt/Storage/DM-Logo.png"
|
||||||
|
}
|
||||||
|
|
@ -15,3 +15,4 @@ werkzeug
|
||||||
mutagen
|
mutagen
|
||||||
flask-limiter
|
flask-limiter
|
||||||
cryptography
|
cryptography
|
||||||
|
Pillow
|
||||||
|
|
|
||||||
|
|
@ -263,6 +263,10 @@
|
||||||
<input type="password" id="smtp_pass" name="smtp_pass" placeholder="{% if email_form.smtp_pass_set %}Stored encrypted — type to replace{% else %}Enter password{% endif %}">
|
<input type="password" id="smtp_pass" name="smtp_pass" placeholder="{% if email_form.smtp_pass_set %}Stored encrypted — type to replace{% else %}Enter password{% endif %}">
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Logo Path</td>
|
||||||
|
<td><input type="text" id="logo_path" name="logo_path" value="{{ email_form.logo_path }}" placeholder="e.g. /mnt/Storage/DM-Logo.png"></td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<button type="submit">Save Email Settings</button>
|
<button type="submit">Save Email Settings</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
80162
test-logo-email.eml
Normal file
80162
test-logo-email.eml
Normal file
File diff suppressed because it is too large
Load diff
BIN
uploads-test/dm-logo.email.jpg
Normal file
BIN
uploads-test/dm-logo.email.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
Reference in a new issue