Merge pull request #138 from simple-login/alias-name

Alias name
This commit is contained in:
Son Nguyen Kim 2020-04-26 11:08:08 +02:00 committed by GitHub
commit 5c48f82f41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 135 additions and 5 deletions

View File

@ -870,6 +870,7 @@ If success, 200 with the list of aliases. Each alias has the following fields:
- id
- email
- name
- enabled
- creation_timestamp
- note
@ -896,6 +897,7 @@ Here's an example:
"creation_date": "2020-04-06 17:57:14+00:00",
"creation_timestamp": 1586195834,
"email": "prefix1.cat@sl.local",
"name": "A Name",
"enabled": true,
"id": 3,
"mailbox": {
@ -920,6 +922,7 @@ Here's an example:
"creation_date": "2020-04-06 17:57:14+00:00",
"creation_timestamp": 1586195834,
"email": "prefix0.hey@sl.local",
"name": null,
"enabled": true,
"id": 2,
"mailbox": {
@ -1046,6 +1049,7 @@ Input:
- `alias_id` in url.
- (optional) `note` in request body
- (optional) `mailbox_id` in request body
- (optional) `name` in request body
Output:
If success, return 200

View File

@ -47,6 +47,7 @@ def serialize_alias_info_v2(alias_info: AliasInfo) -> dict:
"creation_timestamp": alias_info.alias.created_at.timestamp,
"enabled": alias_info.alias.enabled,
"note": alias_info.alias.note,
"name": alias_info.alias.name,
# activity
"nb_forward": alias_info.nb_forward,
"nb_block": alias_info.nb_blocked,

View File

@ -253,6 +253,7 @@ def update_alias(alias_id):
Input:
alias_id: in url
note: in body
name: in body
Output:
200
"""
@ -281,6 +282,11 @@ def update_alias(alias_id):
alias.mailbox_id = mailbox_id
changed = True
if "name" in data:
new_name = data.get("name")
alias.name = new_name
changed = True
if changed:
db.session.commit()

View File

@ -212,10 +212,16 @@
<!-- END Send Email && More button -->
<!-- Collapse section -->
<div class="collapse" id="alias-{{ alias.id }}">
<div class="collapse mt-2" id="alias-{{ alias.id }}">
{% if alias_info.latest_email_log != None %}
<div style="font-size: 12px">
Alias created {{ alias.created_at | dt }}
</div>
{% endif %}
{% if mailboxes|length > 1 %}
<div class="small-text mt-2">Current mailbox</div>
<div class="small-text">Current mailbox</div>
<div class="d-flex">
<div class="flex-grow-1 mr-2">
<select id="mailbox-{{ alias.id }}"
@ -243,14 +249,15 @@
</div>
{% endif %}
<div class="d-flex mt-2">
<div class="small-text mt-2">Alias Note</div>
<div class="d-flex">
<div class="flex-grow-1 mr-2">
<textarea
id="note-{{ alias.id }}"
name="note"
class="form-control"
rows="2"
placeholder="Alias Note.">{{ alias.note or "" }}</textarea>
placeholder="e.g. where the alias is used or why is it created">{{ alias.note or "" }}</textarea>
</div>
<div class="">
@ -261,6 +268,29 @@
</div>
</div>
<div class="small-text mt-2" data-toogle="tooltip"
title="Alias name is used when you send or reply from alias">
Alias name
<i class="fe fe-help-circle"></i>
</div>
<div class="d-flex">
<div class="flex-grow-1 mr-2">
<input id="alias-name-{{ alias.id }}"
value="{{ alias.name or '' }}" class="form-control" placeholder="Alias name">
</div>
<div class="">
<a data-alias="{{ alias.id }}"
class="save-alias-name btn btn-sm btn-outline-primary w-100">
save
</a>
</div>
</div>
<div class="row mt-3">
<div class="col">
<form method="post">
@ -495,5 +525,31 @@
}
})
$(".save-alias-name").on("click", async function () {
let aliasId = $(this).data("alias");
let name = $(`#alias-name-${aliasId}`).val();
try {
let res = await fetch(`/api/aliases/${aliasId}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name: name,
}),
});
if (res.ok) {
toastr.success(`Alias Name Saved`);
} else {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
}
} catch (e) {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
}
})
</script>
{% endblock %}

View File

@ -579,6 +579,9 @@ class Alias(db.Model, ModelMixin):
user_id = db.Column(db.ForeignKey(User.id, ondelete="cascade"), nullable=False)
email = db.Column(db.String(128), unique=True, nullable=False)
# the name to use when user replies/sends from alias
name = db.Column(db.String(128), nullable=True, default=None)
enabled = db.Column(db.Boolean(), default=True, nullable=False)
custom_domain_id = db.Column(

View File

@ -513,7 +513,12 @@ def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> (bool, str
delete_header(msg, "Received")
# make the email comes from alias
add_or_replace_header(msg, "From", alias.email)
if alias.name:
LOG.d("Put alias name in from header")
from_header = formataddr((alias.name, alias.email))
else:
from_header = alias.email
add_or_replace_header(msg, "From", from_header)
# some email providers like ProtonMail adds automatically the Reply-To field
# make sure to delete it

View File

@ -0,0 +1,29 @@
"""empty message
Revision ID: b4146f7d5277
Revises: bd05eac83f5f
Create Date: 2020-04-26 10:26:18.625088
"""
import sqlalchemy_utils
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'b4146f7d5277'
down_revision = 'bd05eac83f5f'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('alias', sa.Column('name', sa.String(length=128), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('alias', 'name')
# ### end Alembic commands ###

View File

@ -155,6 +155,7 @@ def test_get_aliases_v2(flask_client):
# "email": "prefix1.yeah@sl.local",
# "enabled": true,
# "id": 3,
# "name": "Hey hey",
# "latest_activity": {
# "action": "forward",
# "contact": {
@ -173,6 +174,7 @@ def test_get_aliases_v2(flask_client):
# "nb_reply": 0,
# "note": null
# }
assert "name" in r0
assert r0["email"].startswith("prefix1")
assert r0["latest_activity"]["action"] == "forward"
assert "timestamp" in r0["latest_activity"]
@ -333,6 +335,30 @@ def test_update_alias_mailbox(flask_client):
assert r.status_code == 400
def test_update_alias_name(flask_client):
user = User.create(
email="a@b.c", password="password", name="Test User", activated=True
)
db.session.commit()
# create api_key
api_key = ApiKey.create(user.id, "for test")
db.session.commit()
alias = Alias.create_new_random(user)
db.session.commit()
r = flask_client.put(
url_for("api.update_alias", alias_id=alias.id),
headers={"Authentication": api_key.code},
json={"name": "Test Name"},
)
assert r.status_code == 200
alias = Alias.get(alias.id)
assert alias.name == "Test Name"
def test_alias_contacts(flask_client):
user = User.create(
email="a@b.c", password="password", name="Test User", activated=True