Add more From: sender formatting options

This commit is contained in:
Sibren Vasse 2020-05-15 16:14:12 +02:00
parent f577adc0d4
commit a5f24e0227
5 changed files with 122 additions and 43 deletions

View File

@ -206,31 +206,30 @@
<div class="card-body">
<div class="card-title">Sender address format</div>
<div class="mt-1 mb-3">
When your alias receives an email, says from <b>John Wick &lt;john@wick.com&gt;</b>,
When your alias receives an email, it says from: <b>John Wick &lt;john@wick.com&gt;</b>,
SimpleLogin forwards it to your mailbox. <br>
Due to some email constraints, SimpleLogin cannot keep the sender email address
in the original form and needs to <b>transform</b> it to one of the 2 below formats.
in the original form and needs to <b>transform</b> it to one of the formats below.
</div>
<form method="post" action="#sender-format">
<input type="hidden" name="form-name" value="change-sender-format">
<div class="form-check">
<input class="form-check-input" type="radio" name="sender-format" id="exampleRadios1" value="1"
{% if current_user.use_via_format_for_sender %} checked {% endif %}>
<label class="form-check-label" for="exampleRadios1">
<b>john@wick.com via SimpleLogin</b>
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="sender-format" id="exampleRadios2" value="0"
{% if not current_user.use_via_format_for_sender %} checked {% endif %}>
<label class="form-check-label" for="exampleRadios2">
<b>John Wick - john at wick.com</b>
</label>
</div>
<select class="form-control mr-sm-2" name="sender-format">
<option value="{{ SenderFormatEnum.VIA.value }}"
{% if current_user.sender_format == SenderFormatEnum.VIA.value %} selected {% endif %}>
john@wick.com via SimpleLogin</option>
<option value="{{ SenderFormatEnum.AT.value }}"
{% if current_user.sender_format == SenderFormatEnum.AT.value %} selected {% endif %}>
John Wick - john at wick.com</option>
<option value="{{ SenderFormatEnum.A.value }}"
{% if current_user.sender_format == SenderFormatEnum.A.value %} selected {% endif %}>
John Wick - john(a)wick.com</option>
<option value="{{ SenderFormatEnum.FULL.value }}"
{% if current_user.sender_format == SenderFormatEnum.FULL.value %} selected {% endif %}>
John Wick - john@wick.com</option>
</select>
<button class="btn btn-outline-primary mt-3">Update</button>
</form>

View File

@ -30,6 +30,7 @@ from app.models import (
Client,
AliasGeneratorEnum,
ManualSubscription,
SenderFormatEnum,
)
from app.utils import random_string
@ -161,12 +162,11 @@ def setting():
return redirect(url_for("dashboard.setting"))
elif request.form.get("form-name") == "change-sender-format":
sender_format = int(request.form.get("sender-format"))
if sender_format == 0:
current_user.use_via_format_for_sender = False
else:
current_user.use_via_format_for_sender = True
if SenderFormatEnum.has_value(sender_format):
current_user.sender_format = sender_format
db.session.commit()
flash("Your sender format preference has been updated", "success")
db.session.commit()
flash("Your sender format preference has been updated", "success")
return redirect(url_for("dashboard.setting"))
elif request.form.get("form-name") == "export-data":
@ -200,6 +200,7 @@ def setting():
"dashboard/setting.html",
form=form,
PlanEnum=PlanEnum,
SenderFormatEnum=SenderFormatEnum,
promo_form=promo_form,
change_email_form=change_email_form,
pending_email=pending_email,

View File

@ -96,19 +96,29 @@ class File(db.Model, ModelMixin):
return s3.get_url(self.path, expires_in)
class PlanEnum(enum.Enum):
class EnumE(enum.Enum):
@classmethod
def has_value(cls, value: int) -> bool:
return value in set(item.value for item in cls)
class PlanEnum(EnumE):
monthly = 2
yearly = 3
class AliasGeneratorEnum(enum.Enum):
# Specify the format for sender address
class SenderFormatEnum(EnumE):
AT = 0 # John Wick - john at wick.com
VIA = 1 # john@wick.com via SimpleLogin
A = 2 # John Wick - john(a)wick.com
FULL = 3 # John Wick - john@wick.com
class AliasGeneratorEnum(EnumE):
word = 1 # aliases are generated based on random words
uuid = 2 # aliases are generated based on uuid
@classmethod
def has_value(cls, value: int) -> bool:
return value in set(item.value for item in cls)
class User(db.Model, ModelMixin, UserMixin):
__tablename__ = "users"
@ -172,10 +182,13 @@ class User(db.Model, ModelMixin, UserMixin):
profile_picture = db.relationship(File, foreign_keys=[profile_picture_id])
# Use the "via" format for sender address, i.e. "name@example.com via SimpleLogin"
# If False, use the format "Name - name at example.com"
use_via_format_for_sender = db.Column(
db.Boolean, default=True, nullable=False, server_default="1"
# Specify the format for sender address
# John Wick - john at wick.com -> 0
# john@wick.com via SimpleLogin -> 1
# John Wick - john@wick.com -> 2
# John Wick - john@wick.com -> 3
sender_format = db.Column(
db.Integer, default="1", nullable=False, server_default="1"
)
referral_id = db.Column(
@ -868,21 +881,35 @@ class Contact(db.Model, ModelMixin):
def new_addr(self):
"""
Replace original email by reply_email. 2 possible formats:
- first@example.com by SimpleLogin <reply_email> OR
- First Last - first at example.com <reply_email>
Replace original email by reply_email. Possible formats:
- first@example.com via SimpleLogin <reply_email> OR
- First Last - first at example.com <reply_email> OR
- First Last - first(a)example.com <reply_email> OR
- First Last - first@example.com <reply_email> OR
And return new address with RFC 2047 format
`new_email` is a special reply address
"""
user = self.user
if user and user.use_via_format_for_sender:
if (
not user
or not SenderFormatEnum.has_value(user.sender_format)
or user.sender_format == SenderFormatEnum.VIA.value
):
new_name = f"{self.website_email} via SimpleLogin"
else:
elif user.sender_format == SenderFormatEnum.AT.value:
name = self.name or ""
new_name = (
name + (" - " if name else "") + self.website_email.replace("@", " at ")
).strip()
elif user.sender_format == SenderFormatEnum.A.value:
name = self.name or ""
new_name = (
name + (" - " if name else "") + self.website_email.replace("@", "(a)")
).strip()
elif user.sender_format == SenderFormatEnum.FULL.value:
name = self.name or ""
new_name = (name + (" - " if name else "") + self.website_email).strip()
new_addr = formataddr((new_name, self.reply_email)).strip()
return new_addr.strip()

View File

@ -0,0 +1,45 @@
"""empty message
Revision ID: 5cad8fa84386
Revises: a5e3c6693dc6
Create Date: 2020-05-15 15:10:00.096349
"""
import sqlalchemy_utils
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "5cad8fa84386"
down_revision = "a5e3c6693dc6"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column("users", "use_via_format_for_sender", server_default=None)
op.alter_column(
"users",
"use_via_format_for_sender",
new_column_name="sender_format",
type_=sa.Integer(),
postgresql_using="use_via_format_for_sender::integer",
)
op.alter_column("users", "sender_format", server_default="1")
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column("users", "sender_format", server_default=None)
op.alter_column(
"users",
"sender_format",
new_column_name="use_via_format_for_sender",
type_=sa.Boolean(),
postgresql_using="sender_format::boolean",
)
op.alter_column("users", "use_via_format_for_sender", server_default="1")
# ### end Alembic commands ###

View File

@ -1,11 +1,18 @@
from uuid import UUID
import pytest
from uuid import UUID
from app.config import EMAIL_DOMAIN, MAX_NB_EMAIL_FREE_PLAN
from app.email_utils import parseaddr_unicode
from app.extensions import db
from app.models import generate_email, User, Alias, Contact, Mailbox, AliasMailbox
from app.models import (
generate_email,
User,
Alias,
Contact,
Mailbox,
AliasMailbox,
SenderFormatEnum,
)
def test_generate_email(flask_client):
@ -104,7 +111,7 @@ def test_new_addr(flask_client):
alias = Alias.create_new_random(user)
db.session.commit()
# use_via_format_for_sender is by default
# default sender_format is 'via'
c1 = Contact.create(
user_id=user.id,
alias_id=alias.id,
@ -115,8 +122,8 @@ def test_new_addr(flask_client):
db.session.commit()
assert c1.new_addr() == '"abcd@example.com via SimpleLogin" <rep@SL>'
# use_via_format_for_sender = False
user.use_via_format_for_sender = False
# set sender_format = AT
user.sender_format = SenderFormatEnum.AT.value
db.session.commit()
assert c1.new_addr() == '"First Last - abcd at example.com" <rep@SL>'