feat: email notification when receiving private message with opt-out toggle
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions

- New column: users.notify_email_messages (default true)
- Send email via MS Graph when someone receives a private message
- Toggle in /konto/prywatnosc to enable/disable email notifications
- Email includes message preview, sender name, and direct link

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-02-23 09:13:57 +01:00
parent 576303f1b5
commit 97416ffdc1
5 changed files with 67 additions and 1 deletions

View File

@ -777,10 +777,11 @@ def konto_prywatnosc():
user.contact_prefer_email = request.form.get('prefer_email') == 'on'
user.contact_prefer_phone = request.form.get('prefer_phone') == 'on'
user.contact_prefer_portal = request.form.get('prefer_portal') == 'on'
user.notify_email_messages = request.form.get('notify_email_messages') == 'on'
db.commit()
logger.info(f"Privacy settings updated for user: {user.email}")
flash('Ustawienia prywatnosci zostaly zapisane.', 'success')
flash('Ustawienia prywatności zostały zapisane.', 'success')
return redirect(url_for('auth.konto_prywatnosc'))
return render_template('konto/prywatnosc.html',

View File

@ -14,6 +14,7 @@ from . import bp
from database import SessionLocal, User, Company, PrivateMessage, UserNotification, UserBlock, Classified
from utils.helpers import sanitize_input
from utils.decorators import member_required
from email_service import send_email
# ============================================================
@ -191,6 +192,36 @@ def messages_send():
db.add(notification)
db.commit()
# Send email notification if recipient has it enabled
if recipient.notify_email_messages != False and recipient.email:
try:
message_url = url_for('.messages_view', message_id=message.id, _external=True)
settings_url = url_for('auth.konto_prywatnosc', _external=True)
subject_line = f'Nowa wiadomość od {sender_name} — Norda Biznes'
preview = (content[:200] + '...') if len(content) > 200 else content
email_html = f'''
<h2>Masz nową wiadomość</h2>
<p><strong>{sender_name}</strong> wysłał(a) Ci wiadomość na portalu Norda Biznes.</p>
{f'<p><strong>Temat:</strong> {subject}</p>' if subject else ''}
<div style="background: #f8fafc; border-left: 4px solid #3b82f6; padding: 16px; margin: 16px 0; border-radius: 4px;">
<p style="margin: 0; color: #374151;">{preview}</p>
</div>
<p><a href="{message_url}" style="display: inline-block; padding: 10px 24px; background: #3b82f6; color: white; text-decoration: none; border-radius: 6px; font-weight: 500;">Odczytaj wiadomość</a></p>
<p style="font-size: 12px; color: #9ca3af; margin-top: 24px;">Możesz wyłączyć powiadomienia e-mail w <a href="{settings_url}">ustawieniach prywatności</a>.</p>
'''
send_email(
to=[recipient.email],
subject=subject_line,
body_text=f'{sender_name} wysłał(a) Ci wiadomość na portalu Norda Biznes. Odczytaj: {message_url}',
body_html=email_html,
email_type='message_notification',
user_id=recipient.id,
recipient_name=recipient.name
)
except Exception as e:
import logging
logging.getLogger(__name__).warning(f"Failed to send message email notification: {e}")
flash('Wiadomość wysłana.', 'success')
return redirect(url_for('.messages_sent'))
finally:

View File

@ -322,6 +322,9 @@ class User(Base, UserMixin):
contact_prefer_portal = Column(Boolean, default=True) # User prefers portal messages
contact_note = Column(Text, nullable=True) # Additional note (e.g. best hours)
# Email notification preferences
notify_email_messages = Column(Boolean, default=True) # Email when receiving private message
# Relationships
conversations = relationship('AIChatConversation', back_populates='user', cascade='all, delete-orphan')
forum_topics = relationship('ForumTopic', back_populates='author', cascade='all, delete-orphan', primaryjoin='User.id == ForumTopic.author_id')

View File

@ -0,0 +1,16 @@
-- Migration 063: Add email notification preference for private messages
-- Default TRUE so existing users get notified (they can opt-out)
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'users'
AND column_name = 'notify_email_messages'
) THEN
ALTER TABLE users ADD COLUMN notify_email_messages BOOLEAN DEFAULT TRUE;
RAISE NOTICE 'Added notify_email_messages column';
ELSE
RAISE NOTICE 'notify_email_messages column already exists';
END IF;
END $$;

View File

@ -354,6 +354,21 @@
</div>
</div>
<div class="settings-card">
<h2>Powiadomienia e-mail</h2>
<div class="setting-item">
<div class="setting-info">
<div class="setting-label">Nowe wiadomości prywatne</div>
<div class="setting-description">Otrzymuj e-mail, gdy ktoś wyśle Ci wiadomość prywatną na portalu</div>
</div>
<label class="toggle-switch">
<input type="checkbox" name="notify_email_messages" {% if user.notify_email_messages != False %}checked{% endif %}>
<span class="toggle-slider"></span>
</label>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">Zapisz ustawienia</button>
</div>