rename ForwardEmail to Contact

This commit is contained in:
Son NK 2020-03-17 10:56:59 +01:00
parent cc6e8a00a5
commit 17974de746
9 changed files with 103 additions and 116 deletions

View File

@ -13,7 +13,7 @@ from app.dashboard.views.index import get_alias_info, AliasInfo
from app.extensions import db from app.extensions import db
from app.log import LOG from app.log import LOG
from app.models import ForwardEmailLog from app.models import ForwardEmailLog
from app.models import GenEmail, ForwardEmail from app.models import GenEmail, Contact
from app.utils import random_string from app.utils import random_string
@ -199,7 +199,7 @@ def update_alias(alias_id):
return jsonify(note=new_note), 200 return jsonify(note=new_note), 200
def serialize_forward_email(fe: ForwardEmail) -> dict: def serialize_contact(fe: Contact) -> dict:
res = { res = {
"creation_date": fe.created_at.format(), "creation_date": fe.created_at.format(),
@ -220,15 +220,15 @@ def serialize_forward_email(fe: ForwardEmail) -> dict:
def get_alias_contacts(gen_email, page_id: int) -> [dict]: def get_alias_contacts(gen_email, page_id: int) -> [dict]:
q = ( q = (
ForwardEmail.query.filter_by(gen_email_id=gen_email.id) Contact.query.filter_by(gen_email_id=gen_email.id)
.order_by(ForwardEmail.id.desc()) .order_by(Contact.id.desc())
.limit(PAGE_LIMIT) .limit(PAGE_LIMIT)
.offset(page_id * PAGE_LIMIT) .offset(page_id * PAGE_LIMIT)
) )
res = [] res = []
for fe in q.all(): for fe in q.all():
res.append(serialize_forward_email(fe)) res.append(serialize_contact(fe))
return res return res
@ -299,16 +299,16 @@ def create_contact_route(alias_id):
reply_email = f"ra+{random_string(25)}@{EMAIL_DOMAIN}" reply_email = f"ra+{random_string(25)}@{EMAIL_DOMAIN}"
for _ in range(1000): for _ in range(1000):
reply_email = f"ra+{random_string(25)}@{EMAIL_DOMAIN}" reply_email = f"ra+{random_string(25)}@{EMAIL_DOMAIN}"
if not ForwardEmail.get_by(reply_email=reply_email): if not Contact.get_by(reply_email=reply_email):
break break
_, website_email = parseaddr(contact_email) _, website_email = parseaddr(contact_email)
# already been added # already been added
if ForwardEmail.get_by(gen_email_id=gen_email.id, website_email=website_email): if Contact.get_by(gen_email_id=gen_email.id, website_email=website_email):
return jsonify(error="Contact already added"), 409 return jsonify(error="Contact already added"), 409
forward_email = ForwardEmail.create( contact = Contact.create(
gen_email_id=gen_email.id, gen_email_id=gen_email.id,
website_email=website_email, website_email=website_email,
website_from=contact_email, website_from=contact_email,
@ -318,4 +318,4 @@ def create_contact_route(alias_id):
LOG.d("create reverse-alias for %s %s", contact_email, gen_email) LOG.d("create reverse-alias for %s %s", contact_email, gen_email)
db.session.commit() db.session.commit()
return jsonify(**serialize_forward_email(forward_email)), 201 return jsonify(**serialize_contact(contact)), 201

View File

@ -47,33 +47,33 @@
</form> </form>
<div class="row"> <div class="row">
{% for forward_email in forward_emails %} {% for contact in contacts %}
<div class="col-md-6"> <div class="col-md-6">
<div class="my-2 p-2 card {% if forward_email.id == forward_email_id %} highlight-row {% endif %}"> <div class="my-2 p-2 card {% if contact.id == contact_id %} highlight-row {% endif %}">
<div> <div>
<span> <span>
<a href="{{ 'mailto:' + forward_email.website_send_to() }}" <a href="{{ 'mailto:' + contact.website_send_to() }}"
data-toggle="tooltip" data-toggle="tooltip"
title="You can click on this to open your email client. Or use the copy button 👉" title="You can click on this to open your email client. Or use the copy button 👉"
class="font-weight-bold">*************************</a> class="font-weight-bold">*************************</a>
<span class="clipboard btn btn-sm btn-success copy-btn" data-toggle="tooltip" <span class="clipboard btn btn-sm btn-success copy-btn" data-toggle="tooltip"
title="Copy to clipboard" title="Copy to clipboard"
data-clipboard-text="{{ forward_email.website_send_to() }}"> data-clipboard-text="{{ contact.website_send_to() }}">
Copy reverse-alias Copy reverse-alias
</span> </span>
</span> </span>
</div> </div>
<div> <div>
<i class="fe fe-mail"></i> ➡ {{ forward_email.website_from or forward_email.website_email }} <i class="fe fe-mail"></i> ➡ {{ contact.website_from or contact.website_email }}
</div> </div>
<div class="mb-2 text-muted small-text"> <div class="mb-2 text-muted small-text">
Created {{ forward_email.created_at | dt }} <br> Created {{ contact.created_at | dt }} <br>
{% if forward_email.last_reply() %} {% if contact.last_reply() %}
{% set email_log = forward_email.last_reply() %} {% set email_log = contact.last_reply() %}
Last email sent {{ email_log.created_at | dt }} Last email sent {{ email_log.created_at | dt }}
{% endif %} {% endif %}
</div> </div>
@ -81,7 +81,7 @@
<div> <div>
<form method="post"> <form method="post">
<input type="hidden" name="form-name" value="delete"> <input type="hidden" name="form-name" value="delete">
<input type="hidden" name="forward-email-id" value="{{ forward_email.id }}"> <input type="hidden" name="contact-id" value="{{ contact.id }}">
<span class="card-link btn btn-link float-right delete-forward-email"> <span class="card-link btn btn-link float-right delete-forward-email">
Delete Delete
</span> </span>

View File

@ -10,7 +10,7 @@ from app.config import EMAIL_DOMAIN
from app.dashboard.base import dashboard_bp from app.dashboard.base import dashboard_bp
from app.extensions import db from app.extensions import db
from app.log import LOG from app.log import LOG
from app.models import GenEmail, ForwardEmail from app.models import GenEmail, Contact
from app.utils import random_string from app.utils import random_string
@ -47,10 +47,10 @@ class NewContactForm(FlaskForm):
@dashboard_bp.route("/alias_contact_manager/<alias_id>/", methods=["GET", "POST"]) @dashboard_bp.route("/alias_contact_manager/<alias_id>/", methods=["GET", "POST"])
@dashboard_bp.route( @dashboard_bp.route(
"/alias_contact_manager/<alias_id>/<int:forward_email_id>", methods=["GET", "POST"] "/alias_contact_manager/<alias_id>/<contact_id>", methods=["GET", "POST"]
) )
@login_required @login_required
def alias_contact_manager(alias_id, forward_email_id=None): def alias_contact_manager(alias_id, contact_id=None):
gen_email = GenEmail.get(alias_id) gen_email = GenEmail.get(alias_id)
# sanity check # sanity check
@ -71,15 +71,16 @@ def alias_contact_manager(alias_id, forward_email_id=None):
# generate a reply_email, make sure it is unique # generate a reply_email, make sure it is unique
# not use while to avoid infinite loop # not use while to avoid infinite loop
reply_email = f"ra+{random_string(25)}@{EMAIL_DOMAIN}"
for _ in range(1000): for _ in range(1000):
reply_email = f"ra+{random_string(25)}@{EMAIL_DOMAIN}" reply_email = f"ra+{random_string(25)}@{EMAIL_DOMAIN}"
if not ForwardEmail.get_by(reply_email=reply_email): if not Contact.get_by(reply_email=reply_email):
break break
_, website_email = parseaddr(contact_email) _, website_email = parseaddr(contact_email)
# already been added # already been added
if ForwardEmail.get_by( if Contact.get_by(
gen_email_id=gen_email.id, website_email=website_email gen_email_id=gen_email.id, website_email=website_email
): ):
flash(f"{website_email} is already added", "error") flash(f"{website_email} is already added", "error")
@ -87,7 +88,7 @@ def alias_contact_manager(alias_id, forward_email_id=None):
url_for("dashboard.alias_contact_manager", alias_id=alias_id) url_for("dashboard.alias_contact_manager", alias_id=alias_id)
) )
forward_email = ForwardEmail.create( contact = Contact.create(
gen_email_id=gen_email.id, gen_email_id=gen_email.id,
website_email=website_email, website_email=website_email,
website_from=contact_email, website_from=contact_email,
@ -102,26 +103,26 @@ def alias_contact_manager(alias_id, forward_email_id=None):
url_for( url_for(
"dashboard.alias_contact_manager", "dashboard.alias_contact_manager",
alias_id=alias_id, alias_id=alias_id,
forward_email_id=forward_email.id, contact_id=contact.id,
) )
) )
elif request.form.get("form-name") == "delete": elif request.form.get("form-name") == "delete":
forward_email_id = request.form.get("forward-email-id") contact_id = request.form.get("contact-id")
forward_email = ForwardEmail.get(forward_email_id) contact = Contact.get(contact_id)
if not forward_email: if not contact:
flash("Unknown error. Refresh the page", "warning") flash("Unknown error. Refresh the page", "warning")
return redirect( return redirect(
url_for("dashboard.alias_contact_manager", alias_id=alias_id) url_for("dashboard.alias_contact_manager", alias_id=alias_id)
) )
elif forward_email.gen_email_id != gen_email.id: elif contact.gen_email_id != gen_email.id:
flash("You cannot delete reverse-alias", "warning") flash("You cannot delete reverse-alias", "warning")
return redirect( return redirect(
url_for("dashboard.alias_contact_manager", alias_id=alias_id) url_for("dashboard.alias_contact_manager", alias_id=alias_id)
) )
contact_name = forward_email.website_from contact_name = contact.website_from
ForwardEmail.delete(forward_email_id) Contact.delete(contact_id)
db.session.commit() db.session.commit()
flash(f"Reverse-alias for {contact_name} has been deleted", "success") flash(f"Reverse-alias for {contact_name} has been deleted", "success")
@ -130,19 +131,17 @@ def alias_contact_manager(alias_id, forward_email_id=None):
url_for("dashboard.alias_contact_manager", alias_id=alias_id) url_for("dashboard.alias_contact_manager", alias_id=alias_id)
) )
# make sure highlighted forward_email is at array start # make sure highlighted contact is at array start
forward_emails = gen_email.forward_emails contacts = gen_email.contacts
if forward_email_id: if contact_id:
forward_emails = sorted( contacts = sorted(contacts, key=lambda fe: fe.id == contact_id, reverse=True)
forward_emails, key=lambda fe: fe.id == forward_email_id, reverse=True
)
return render_template( return render_template(
"dashboard/alias_contact_manager.html", "dashboard/alias_contact_manager.html",
forward_emails=forward_emails, contacts=contacts,
alias=gen_email.email, alias=gen_email.email,
gen_email=gen_email, gen_email=gen_email,
new_contact_form=new_contact_form, new_contact_form=new_contact_form,
forward_email_id=forward_email_id, contact_id=contact_id,
) )

View File

@ -5,7 +5,7 @@ from flask_login import login_required, current_user
from app.config import PAGE_LIMIT from app.config import PAGE_LIMIT
from app.dashboard.base import dashboard_bp from app.dashboard.base import dashboard_bp
from app.extensions import db from app.extensions import db
from app.models import GenEmail, ForwardEmailLog, ForwardEmail from app.models import GenEmail, ForwardEmailLog, Contact
class AliasLog: class AliasLog:
@ -42,9 +42,9 @@ def alias_log(alias_id, page_id):
logs = get_alias_log(gen_email, page_id) logs = get_alias_log(gen_email, page_id)
base = ( base = (
db.session.query(ForwardEmail, ForwardEmailLog) db.session.query(Contact, ForwardEmailLog)
.filter(ForwardEmail.id == ForwardEmailLog.forward_id) .filter(Contact.id == ForwardEmailLog.forward_id)
.filter(ForwardEmail.gen_email_id == gen_email.id) .filter(Contact.gen_email_id == gen_email.id)
) )
total = base.count() total = base.count()
email_forwarded = ( email_forwarded = (
@ -66,9 +66,9 @@ def get_alias_log(gen_email: GenEmail, page_id=0):
mailbox = gen_email.mailbox_email() mailbox = gen_email.mailbox_email()
q = ( q = (
db.session.query(ForwardEmail, ForwardEmailLog) db.session.query(Contact, ForwardEmailLog)
.filter(ForwardEmail.id == ForwardEmailLog.forward_id) .filter(Contact.id == ForwardEmailLog.forward_id)
.filter(ForwardEmail.gen_email_id == gen_email.id) .filter(Contact.gen_email_id == gen_email.id)
.order_by(ForwardEmailLog.id.desc()) .order_by(ForwardEmailLog.id.desc())
.limit(PAGE_LIMIT) .limit(PAGE_LIMIT)
.offset(page_id * PAGE_LIMIT) .offset(page_id * PAGE_LIMIT)

View File

@ -12,7 +12,7 @@ from app.log import LOG
from app.models import ( from app.models import (
GenEmail, GenEmail,
ClientUser, ClientUser,
ForwardEmail, Contact,
ForwardEmailLog, ForwardEmailLog,
DeletedAlias, DeletedAlias,
AliasGeneratorEnum, AliasGeneratorEnum,
@ -202,11 +202,9 @@ def get_alias_info(
aliases = {} # dict of alias and AliasInfo aliases = {} # dict of alias and AliasInfo
q = ( q = (
db.session.query(GenEmail, ForwardEmail, ForwardEmailLog, Mailbox) db.session.query(GenEmail, Contact, ForwardEmailLog, Mailbox)
.join(ForwardEmail, GenEmail.id == ForwardEmail.gen_email_id, isouter=True) .join(Contact, GenEmail.id == Contact.gen_email_id, isouter=True)
.join( .join(ForwardEmailLog, Contact.id == ForwardEmailLog.forward_id, isouter=True)
ForwardEmailLog, ForwardEmail.id == ForwardEmailLog.forward_id, isouter=True
)
.join(Mailbox, GenEmail.mailbox_id == Mailbox.id, isouter=True) .join(Mailbox, GenEmail.mailbox_id == Mailbox.id, isouter=True)
.filter(GenEmail.user_id == user.id) .filter(GenEmail.user_id == user.id)
.order_by(GenEmail.created_at.desc()) .order_by(GenEmail.created_at.desc())

View File

@ -698,7 +698,7 @@ class ClientUser(db.Model, ModelMixin):
return res return res
class ForwardEmail(db.Model, ModelMixin): class Contact(db.Model, ModelMixin):
""" """
Store configuration of sender (website-email) and alias. Store configuration of sender (website-email) and alias.
""" """
@ -724,7 +724,7 @@ class ForwardEmail(db.Model, ModelMixin):
# it has the prefix "reply+" to distinguish with other email # it has the prefix "reply+" to distinguish with other email
reply_email = db.Column(db.String(512), nullable=False) reply_email = db.Column(db.String(512), nullable=False)
gen_email = db.relationship(GenEmail, backref="forward_emails") gen_email = db.relationship(GenEmail, backref="contacts")
def website_send_to(self): def website_send_to(self):
"""return the email address with name. """return the email address with name.
@ -755,7 +755,7 @@ class ForwardEmail(db.Model, ModelMixin):
class ForwardEmailLog(db.Model, ModelMixin): class ForwardEmailLog(db.Model, ModelMixin):
forward_id = db.Column( forward_id = db.Column(
db.ForeignKey(ForwardEmail.id, ondelete="cascade"), nullable=False db.ForeignKey(Contact.id, ondelete="cascade"), nullable=False
) )
# whether this is a reply # whether this is a reply
@ -774,7 +774,7 @@ class ForwardEmailLog(db.Model, ModelMixin):
) )
refused_email = db.relationship("RefusedEmail") refused_email = db.relationship("RefusedEmail")
forward = db.relationship(ForwardEmail) forward = db.relationship(Contact)
class Subscription(db.Model, ModelMixin): class Subscription(db.Model, ModelMixin):

View File

@ -12,7 +12,7 @@ from app.models import (
User, User,
GenEmail, GenEmail,
ForwardEmailLog, ForwardEmailLog,
ForwardEmail, Contact,
CustomDomain, CustomDomain,
Client, Client,
ManualSubscription, ManualSubscription,
@ -119,9 +119,9 @@ def stats():
LOG.d("total number alias %s", nb_gen_email) LOG.d("total number alias %s", nb_gen_email)
# nb mails forwarded # nb mails forwarded
q = db.session.query(ForwardEmailLog, ForwardEmail, GenEmail, User).filter( q = db.session.query(ForwardEmailLog, Contact, GenEmail, User).filter(
ForwardEmailLog.forward_id == ForwardEmail.id, ForwardEmailLog.forward_id == Contact.id,
ForwardEmail.gen_email_id == GenEmail.id, Contact.gen_email_id == GenEmail.id,
GenEmail.user_id == User.id, GenEmail.user_id == User.id,
) )
for ie in IGNORED_EMAILS: for ie in IGNORED_EMAILS:

View File

@ -70,7 +70,7 @@ from app.extensions import db
from app.log import LOG from app.log import LOG
from app.models import ( from app.models import (
GenEmail, GenEmail,
ForwardEmail, Contact,
ForwardEmailLog, ForwardEmailLog,
CustomDomain, CustomDomain,
Directory, Directory,
@ -207,21 +207,17 @@ def try_auto_create_catch_all_domain(alias: str) -> Optional[GenEmail]:
return gen_email return gen_email
def get_or_create_forward_email( def get_or_create_contact(website_from_header: str, gen_email: GenEmail) -> Contact:
website_from_header: str, gen_email: GenEmail
) -> ForwardEmail:
""" """
website_from_header can be the full-form email, i.e. "First Last <email@example.com>" website_from_header can be the full-form email, i.e. "First Last <email@example.com>"
""" """
_, website_email = parseaddr(website_from_header) _, website_email = parseaddr(website_from_header)
forward_email = ForwardEmail.get_by( contact = Contact.get_by(gen_email_id=gen_email.id, website_email=website_email)
gen_email_id=gen_email.id, website_email=website_email if contact:
)
if forward_email:
# update the website_from if needed # update the website_from if needed
if forward_email.website_from != website_from_header: if contact.website_from != website_from_header:
LOG.d("Update From header for %s", forward_email) LOG.d("Update From header for %s", contact)
forward_email.website_from = website_from_header contact.website_from = website_from_header
db.session.commit() db.session.commit()
else: else:
LOG.debug( LOG.debug(
@ -234,12 +230,12 @@ def get_or_create_forward_email(
# not use while loop to avoid infinite loop # not use while loop to avoid infinite loop
reply_email = f"reply+{random_string(30)}@{EMAIL_DOMAIN}" reply_email = f"reply+{random_string(30)}@{EMAIL_DOMAIN}"
for _ in range(1000): for _ in range(1000):
if not ForwardEmail.get_by(reply_email=reply_email): if not Contact.get_by(reply_email=reply_email):
# found! # found!
break break
reply_email = f"reply+{random_string(30)}@{EMAIL_DOMAIN}" reply_email = f"reply+{random_string(30)}@{EMAIL_DOMAIN}"
forward_email = ForwardEmail.create( contact = Contact.create(
gen_email_id=gen_email.id, gen_email_id=gen_email.id,
website_email=website_email, website_email=website_email,
website_from=website_from_header, website_from=website_from_header,
@ -247,7 +243,7 @@ def get_or_create_forward_email(
) )
db.session.commit() db.session.commit()
return forward_email return contact
def should_append_alias(msg, alias): def should_append_alias(msg, alias):
@ -317,8 +313,8 @@ def handle_forward(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str:
LOG.d("Encrypt message using mailbox %s", mailbox) LOG.d("Encrypt message using mailbox %s", mailbox)
msg = prepare_pgp_message(msg, mailbox.pgp_finger_print) msg = prepare_pgp_message(msg, mailbox.pgp_finger_print)
forward_email = get_or_create_forward_email(msg["From"], gen_email) contact = get_or_create_contact(msg["From"], gen_email)
forward_log = ForwardEmailLog.create(forward_id=forward_email.id) forward_log = ForwardEmailLog.create(forward_id=contact.id)
if gen_email.enabled: if gen_email.enabled:
# add custom header # add custom header
@ -338,7 +334,7 @@ def handle_forward(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str:
+ (" - " if website_name else "") + (" - " if website_name else "")
+ website_email.replace("@", " at ") + website_email.replace("@", " at ")
) )
from_header = formataddr((new_website_name, forward_email.reply_email)) from_header = formataddr((new_website_name, contact.reply_email))
add_or_replace_header(msg, "From", from_header) add_or_replace_header(msg, "From", from_header)
LOG.d("new from header:%s", from_header) LOG.d("new from header:%s", from_header)
@ -373,7 +369,7 @@ def handle_forward(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str:
# encode message raw directly instead # encode message raw directly instead
msg_raw = msg.as_string().encode() msg_raw = msg.as_string().encode()
smtp.sendmail( smtp.sendmail(
forward_email.reply_email, contact.reply_email,
mailbox_email, mailbox_email,
msg_raw, msg_raw,
envelope.mail_options, envelope.mail_options,
@ -395,12 +391,12 @@ def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str:
LOG.warning(f"Reply email {reply_email} has wrong domain") LOG.warning(f"Reply email {reply_email} has wrong domain")
return "550 wrong reply email" return "550 wrong reply email"
forward_email = ForwardEmail.get_by(reply_email=reply_email) contact = Contact.get_by(reply_email=reply_email)
if not forward_email: if not contact:
LOG.warning(f"No such forward-email with {reply_email} as reply-email") LOG.warning(f"No such forward-email with {reply_email} as reply-email")
return "550 wrong reply email" return "550 wrong reply email"
alias: str = forward_email.gen_email.email alias: str = contact.gen_email.email
alias_domain = alias[alias.find("@") + 1 :] alias_domain = alias[alias.find("@") + 1 :]
# alias must end with one of the ALIAS_DOMAINS or custom-domain # alias must end with one of the ALIAS_DOMAINS or custom-domain
@ -408,7 +404,7 @@ def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str:
if not CustomDomain.get_by(domain=alias_domain): if not CustomDomain.get_by(domain=alias_domain):
return "550 alias unknown by SimpleLogin" return "550 alias unknown by SimpleLogin"
gen_email = forward_email.gen_email gen_email = contact.gen_email
user = gen_email.user user = gen_email.user
mailbox_email = gen_email.mailbox_email() mailbox_email = gen_email.mailbox_email()
@ -420,12 +416,12 @@ def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str:
LOG.error( LOG.error(
"Bounce when sending to alias %s from %s, user %s", "Bounce when sending to alias %s from %s, user %s",
alias, alias,
forward_email.website_from, contact.website_from,
gen_email.user, gen_email.user,
) )
handle_bounce( handle_bounce(
alias, envelope, forward_email, gen_email, msg, smtp, user, mailbox_email alias, envelope, contact, gen_email, msg, smtp, user, mailbox_email
) )
return "550 ignored" return "550 ignored"
@ -485,10 +481,10 @@ def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str:
# remove sender header if present as this could reveal user real email # remove sender header if present as this could reveal user real email
delete_header(msg, "Sender") delete_header(msg, "Sender")
add_or_replace_header(msg, "To", forward_email.website_email) add_or_replace_header(msg, "To", contact.website_email)
# add List-Unsubscribe header # add List-Unsubscribe header
unsubscribe_link = f"{URL}/dashboard/unsubscribe/{forward_email.gen_email_id}" unsubscribe_link = f"{URL}/dashboard/unsubscribe/{contact.gen_email_id}"
add_or_replace_header(msg, "List-Unsubscribe", f"<{unsubscribe_link}>") add_or_replace_header(msg, "List-Unsubscribe", f"<{unsubscribe_link}>")
add_or_replace_header(msg, "List-Unsubscribe-Post", "List-Unsubscribe=One-Click") add_or_replace_header(msg, "List-Unsubscribe-Post", "List-Unsubscribe=One-Click")
@ -498,7 +494,7 @@ def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str:
LOG.d( LOG.d(
"send email from %s to %s, mail_options:%s,rcpt_options:%s", "send email from %s to %s, mail_options:%s,rcpt_options:%s",
alias, alias,
forward_email.website_email, contact.website_email,
envelope.mail_options, envelope.mail_options,
envelope.rcpt_options, envelope.rcpt_options,
) )
@ -514,29 +510,23 @@ def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str:
msg_raw = msg.as_string().encode() msg_raw = msg.as_string().encode()
smtp.sendmail( smtp.sendmail(
alias, alias,
forward_email.website_email, contact.website_email,
msg_raw, msg_raw,
envelope.mail_options, envelope.mail_options,
envelope.rcpt_options, envelope.rcpt_options,
) )
ForwardEmailLog.create(forward_id=forward_email.id, is_reply=True) ForwardEmailLog.create(forward_id=contact.id, is_reply=True)
db.session.commit() db.session.commit()
return "250 Message accepted for delivery" return "250 Message accepted for delivery"
def handle_bounce( def handle_bounce(alias, envelope, contact, gen_email, msg, smtp, user, mailbox_email):
alias, envelope, forward_email, gen_email, msg, smtp, user, mailbox_email fel: ForwardEmailLog = ForwardEmailLog.create(forward_id=contact.id, bounced=True)
):
fel: ForwardEmailLog = ForwardEmailLog.create(
forward_id=forward_email.id, bounced=True
)
db.session.commit() db.session.commit()
nb_bounced = ForwardEmailLog.filter_by( nb_bounced = ForwardEmailLog.filter_by(forward_id=contact.id, bounced=True).count()
forward_id=forward_email.id, bounced=True
).count()
disable_alias_link = f"{URL}/dashboard/unsubscribe/{gen_email.id}" disable_alias_link = f"{URL}/dashboard/unsubscribe/{gen_email.id}"
# Store the bounced email # Store the bounced email
@ -569,19 +559,19 @@ def handle_bounce(
LOG.d( LOG.d(
"Inform user %s about bounced email sent by %s to alias %s", "Inform user %s about bounced email sent by %s to alias %s",
user, user,
forward_email.website_from, contact.website_from,
alias, alias,
) )
send_email( send_email(
# use user mail here as only user is authenticated to see the refused email # use user mail here as only user is authenticated to see the refused email
user.email, user.email,
f"Email from {forward_email.website_from} to {alias} cannot be delivered to your inbox", f"Email from {contact.website_from} to {alias} cannot be delivered to your inbox",
render( render(
"transactional/bounced-email.txt", "transactional/bounced-email.txt",
name=user.name, name=user.name,
alias=alias, alias=alias,
website_from=forward_email.website_from, website_from=contact.website_from,
website_email=forward_email.website_email, website_email=contact.website_email,
disable_alias_link=disable_alias_link, disable_alias_link=disable_alias_link,
refused_email_url=refused_email_url, refused_email_url=refused_email_url,
mailbox_email=mailbox_email, mailbox_email=mailbox_email,
@ -590,8 +580,8 @@ def handle_bounce(
"transactional/bounced-email.html", "transactional/bounced-email.html",
name=user.name, name=user.name,
alias=alias, alias=alias,
website_from=forward_email.website_from, website_from=contact.website_from,
website_email=forward_email.website_email, website_email=contact.website_email,
disable_alias_link=disable_alias_link, disable_alias_link=disable_alias_link,
refused_email_url=refused_email_url, refused_email_url=refused_email_url,
mailbox_email=mailbox_email, mailbox_email=mailbox_email,
@ -604,7 +594,7 @@ def handle_bounce(
LOG.d( LOG.d(
"Bounce happens again with alias %s from %s. Disable alias now ", "Bounce happens again with alias %s from %s. Disable alias now ",
alias, alias,
forward_email.website_from, contact.website_from,
) )
gen_email.enabled = False gen_email.enabled = False
db.session.commit() db.session.commit()
@ -612,13 +602,13 @@ def handle_bounce(
send_email( send_email(
# use user mail here as only user is authenticated to see the refused email # use user mail here as only user is authenticated to see the refused email
user.email, user.email,
f"Alias {alias} has been disabled due to second undelivered email from {forward_email.website_from}", f"Alias {alias} has been disabled due to second undelivered email from {contact.website_from}",
render( render(
"transactional/automatic-disable-alias.txt", "transactional/automatic-disable-alias.txt",
name=user.name, name=user.name,
alias=alias, alias=alias,
website_from=forward_email.website_from, website_from=contact.website_from,
website_email=forward_email.website_email, website_email=contact.website_email,
refused_email_url=refused_email_url, refused_email_url=refused_email_url,
mailbox_email=mailbox_email, mailbox_email=mailbox_email,
), ),
@ -626,8 +616,8 @@ def handle_bounce(
"transactional/automatic-disable-alias.html", "transactional/automatic-disable-alias.html",
name=user.name, name=user.name,
alias=alias, alias=alias,
website_from=forward_email.website_from, website_from=contact.website_from,
website_email=forward_email.website_email, website_email=contact.website_email,
refused_email_url=refused_email_url, refused_email_url=refused_email_url,
mailbox_email=mailbox_email, mailbox_email=mailbox_email,
), ),

View File

@ -4,7 +4,7 @@ from flask import url_for
from app.config import EMAIL_DOMAIN, MAX_NB_EMAIL_FREE_PLAN, PAGE_LIMIT from app.config import EMAIL_DOMAIN, MAX_NB_EMAIL_FREE_PLAN, PAGE_LIMIT
from app.extensions import db from app.extensions import db
from app.models import User, ApiKey, GenEmail, ForwardEmail, ForwardEmailLog from app.models import User, ApiKey, GenEmail, Contact, ForwardEmailLog
from app.utils import random_word from app.utils import random_word
@ -128,7 +128,7 @@ def test_alias_activities(flask_client):
db.session.commit() db.session.commit()
# create some alias log # create some alias log
forward_email = ForwardEmail.create( contact = Contact.create(
website_email="marketing@example.com", website_email="marketing@example.com",
reply_email="reply@a.b", reply_email="reply@a.b",
gen_email_id=gen_email.id, gen_email_id=gen_email.id,
@ -136,10 +136,10 @@ def test_alias_activities(flask_client):
db.session.commit() db.session.commit()
for _ in range(int(PAGE_LIMIT / 2)): for _ in range(int(PAGE_LIMIT / 2)):
ForwardEmailLog.create(forward_id=forward_email.id, is_reply=True) ForwardEmailLog.create(forward_id=contact.id, is_reply=True)
for _ in range(int(PAGE_LIMIT / 2) + 2): for _ in range(int(PAGE_LIMIT / 2) + 2):
ForwardEmailLog.create(forward_id=forward_email.id, blocked=True) ForwardEmailLog.create(forward_id=contact.id, blocked=True)
r = flask_client.get( r = flask_client.get(
url_for("api.get_alias_activities", alias_id=gen_email.id, page_id=0), url_for("api.get_alias_activities", alias_id=gen_email.id, page_id=0),
@ -200,14 +200,14 @@ def test_alias_contacts(flask_client):
# create some alias log # create some alias log
for i in range(PAGE_LIMIT + 1): for i in range(PAGE_LIMIT + 1):
forward_email = ForwardEmail.create( contact = Contact.create(
website_email=f"marketing-{i}@example.com", website_email=f"marketing-{i}@example.com",
reply_email=f"reply-{i}@a.b", reply_email=f"reply-{i}@a.b",
gen_email_id=gen_email.id, gen_email_id=gen_email.id,
) )
db.session.commit() db.session.commit()
ForwardEmailLog.create(forward_id=forward_email.id, is_reply=True) ForwardEmailLog.create(forward_id=contact.id, is_reply=True)
db.session.commit() db.session.commit()
r = flask_client.get( r = flask_client.get(