mirror of
https://github.com/simple-login/app.git
synced 2024-09-28 20:51:29 +02:00
commit
5c48f82f41
@ -870,6 +870,7 @@ If success, 200 with the list of aliases. Each alias has the following fields:
|
|||||||
|
|
||||||
- id
|
- id
|
||||||
- email
|
- email
|
||||||
|
- name
|
||||||
- enabled
|
- enabled
|
||||||
- creation_timestamp
|
- creation_timestamp
|
||||||
- note
|
- note
|
||||||
@ -896,6 +897,7 @@ Here's an example:
|
|||||||
"creation_date": "2020-04-06 17:57:14+00:00",
|
"creation_date": "2020-04-06 17:57:14+00:00",
|
||||||
"creation_timestamp": 1586195834,
|
"creation_timestamp": 1586195834,
|
||||||
"email": "prefix1.cat@sl.local",
|
"email": "prefix1.cat@sl.local",
|
||||||
|
"name": "A Name",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"id": 3,
|
"id": 3,
|
||||||
"mailbox": {
|
"mailbox": {
|
||||||
@ -920,6 +922,7 @@ Here's an example:
|
|||||||
"creation_date": "2020-04-06 17:57:14+00:00",
|
"creation_date": "2020-04-06 17:57:14+00:00",
|
||||||
"creation_timestamp": 1586195834,
|
"creation_timestamp": 1586195834,
|
||||||
"email": "prefix0.hey@sl.local",
|
"email": "prefix0.hey@sl.local",
|
||||||
|
"name": null,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"mailbox": {
|
"mailbox": {
|
||||||
@ -1046,6 +1049,7 @@ Input:
|
|||||||
- `alias_id` in url.
|
- `alias_id` in url.
|
||||||
- (optional) `note` in request body
|
- (optional) `note` in request body
|
||||||
- (optional) `mailbox_id` in request body
|
- (optional) `mailbox_id` in request body
|
||||||
|
- (optional) `name` in request body
|
||||||
|
|
||||||
Output:
|
Output:
|
||||||
If success, return 200
|
If success, return 200
|
||||||
|
@ -47,6 +47,7 @@ def serialize_alias_info_v2(alias_info: AliasInfo) -> dict:
|
|||||||
"creation_timestamp": alias_info.alias.created_at.timestamp,
|
"creation_timestamp": alias_info.alias.created_at.timestamp,
|
||||||
"enabled": alias_info.alias.enabled,
|
"enabled": alias_info.alias.enabled,
|
||||||
"note": alias_info.alias.note,
|
"note": alias_info.alias.note,
|
||||||
|
"name": alias_info.alias.name,
|
||||||
# activity
|
# activity
|
||||||
"nb_forward": alias_info.nb_forward,
|
"nb_forward": alias_info.nb_forward,
|
||||||
"nb_block": alias_info.nb_blocked,
|
"nb_block": alias_info.nb_blocked,
|
||||||
|
@ -253,6 +253,7 @@ def update_alias(alias_id):
|
|||||||
Input:
|
Input:
|
||||||
alias_id: in url
|
alias_id: in url
|
||||||
note: in body
|
note: in body
|
||||||
|
name: in body
|
||||||
Output:
|
Output:
|
||||||
200
|
200
|
||||||
"""
|
"""
|
||||||
@ -281,6 +282,11 @@ def update_alias(alias_id):
|
|||||||
alias.mailbox_id = mailbox_id
|
alias.mailbox_id = mailbox_id
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
|
if "name" in data:
|
||||||
|
new_name = data.get("name")
|
||||||
|
alias.name = new_name
|
||||||
|
changed = True
|
||||||
|
|
||||||
if changed:
|
if changed:
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
@ -212,10 +212,16 @@
|
|||||||
<!-- END Send Email && More button -->
|
<!-- END Send Email && More button -->
|
||||||
|
|
||||||
<!-- Collapse section -->
|
<!-- 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 %}
|
{% 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="d-flex">
|
||||||
<div class="flex-grow-1 mr-2">
|
<div class="flex-grow-1 mr-2">
|
||||||
<select id="mailbox-{{ alias.id }}"
|
<select id="mailbox-{{ alias.id }}"
|
||||||
@ -243,14 +249,15 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% 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">
|
<div class="flex-grow-1 mr-2">
|
||||||
<textarea
|
<textarea
|
||||||
id="note-{{ alias.id }}"
|
id="note-{{ alias.id }}"
|
||||||
name="note"
|
name="note"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
rows="2"
|
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>
|
||||||
|
|
||||||
<div class="">
|
<div class="">
|
||||||
@ -261,6 +268,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</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="row mt-3">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<form method="post">
|
<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>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -579,6 +579,9 @@ class Alias(db.Model, ModelMixin):
|
|||||||
user_id = db.Column(db.ForeignKey(User.id, ondelete="cascade"), nullable=False)
|
user_id = db.Column(db.ForeignKey(User.id, ondelete="cascade"), nullable=False)
|
||||||
email = db.Column(db.String(128), unique=True, 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)
|
enabled = db.Column(db.Boolean(), default=True, nullable=False)
|
||||||
|
|
||||||
custom_domain_id = db.Column(
|
custom_domain_id = db.Column(
|
||||||
|
@ -513,7 +513,12 @@ def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> (bool, str
|
|||||||
delete_header(msg, "Received")
|
delete_header(msg, "Received")
|
||||||
|
|
||||||
# make the email comes from alias
|
# 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
|
# some email providers like ProtonMail adds automatically the Reply-To field
|
||||||
# make sure to delete it
|
# make sure to delete it
|
||||||
|
29
migrations/versions/2020_042610_b4146f7d5277_.py
Normal file
29
migrations/versions/2020_042610_b4146f7d5277_.py
Normal 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 ###
|
@ -155,6 +155,7 @@ def test_get_aliases_v2(flask_client):
|
|||||||
# "email": "prefix1.yeah@sl.local",
|
# "email": "prefix1.yeah@sl.local",
|
||||||
# "enabled": true,
|
# "enabled": true,
|
||||||
# "id": 3,
|
# "id": 3,
|
||||||
|
# "name": "Hey hey",
|
||||||
# "latest_activity": {
|
# "latest_activity": {
|
||||||
# "action": "forward",
|
# "action": "forward",
|
||||||
# "contact": {
|
# "contact": {
|
||||||
@ -173,6 +174,7 @@ def test_get_aliases_v2(flask_client):
|
|||||||
# "nb_reply": 0,
|
# "nb_reply": 0,
|
||||||
# "note": null
|
# "note": null
|
||||||
# }
|
# }
|
||||||
|
assert "name" in r0
|
||||||
assert r0["email"].startswith("prefix1")
|
assert r0["email"].startswith("prefix1")
|
||||||
assert r0["latest_activity"]["action"] == "forward"
|
assert r0["latest_activity"]["action"] == "forward"
|
||||||
assert "timestamp" in r0["latest_activity"]
|
assert "timestamp" in r0["latest_activity"]
|
||||||
@ -333,6 +335,30 @@ def test_update_alias_mailbox(flask_client):
|
|||||||
assert r.status_code == 400
|
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):
|
def test_alias_contacts(flask_client):
|
||||||
user = User.create(
|
user = User.create(
|
||||||
email="a@b.c", password="password", name="Test User", activated=True
|
email="a@b.c", password="password", name="Test User", activated=True
|
||||||
|
Loading…
Reference in New Issue
Block a user