parent
3ed9c3d6fe
commit
b84eb13ab5
|
@ -2293,3 +2293,10 @@ class Payout(db.Model, ModelMixin):
|
|||
comment = db.Column(db.Text)
|
||||
|
||||
user = db.relationship(User)
|
||||
|
||||
|
||||
class IgnoredEmail(db.Model, ModelMixin):
|
||||
"""If an email has mail_from and rcpt_to present in this table, discard it by returning 250 status."""
|
||||
|
||||
mail_from = db.Column(db.String(512), nullable=False)
|
||||
rcpt_to = db.Column(db.String(512), nullable=False)
|
||||
|
|
|
@ -120,6 +120,7 @@ from app.models import (
|
|||
Mailbox,
|
||||
Bounce,
|
||||
TransactionalEmail,
|
||||
IgnoredEmail,
|
||||
)
|
||||
from app.pgp_utils import PGPException, sign_data_with_pgpy, sign_data
|
||||
from app.utils import sanitize_email
|
||||
|
@ -1526,6 +1527,17 @@ def handle_bounce(envelope, email_log: EmailLog, msg: Message) -> str:
|
|||
return "550 SL E26 Email cannot be forwarded to mailbox"
|
||||
|
||||
|
||||
def should_ignore(mail_from: str, rcpt_tos: List[str]) -> bool:
|
||||
if len(rcpt_tos) != 1:
|
||||
return False
|
||||
|
||||
rcpt_to = rcpt_tos[0]
|
||||
if IgnoredEmail.get_by(mail_from=mail_from, rcpt_to=rcpt_to):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def handle(envelope: Envelope) -> str:
|
||||
"""Return SMTP status"""
|
||||
|
||||
|
@ -1535,6 +1547,10 @@ def handle(envelope: Envelope) -> str:
|
|||
envelope.mail_from = mail_from
|
||||
envelope.rcpt_tos = rcpt_tos
|
||||
|
||||
if should_ignore(mail_from, rcpt_tos):
|
||||
LOG.e("Ignore email mail_from=%s rcpt_to=%s", mail_from, rcpt_tos)
|
||||
return "250 email can't be sent from a reverse-alias"
|
||||
|
||||
msg = email.message_from_bytes(envelope.original_content)
|
||||
postfix_queue_id = get_queue_id(msg)
|
||||
if postfix_queue_id:
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
"""empty message
|
||||
|
||||
Revision ID: 29ea13ed76f9
|
||||
Revises: a5e643d562c9
|
||||
Create Date: 2021-06-22 17:51:27.343947
|
||||
|
||||
"""
|
||||
import sqlalchemy_utils
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '29ea13ed76f9'
|
||||
down_revision = 'a5e643d562c9'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('ignored_email',
|
||||
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
|
||||
sa.Column('created_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=False),
|
||||
sa.Column('updated_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=True),
|
||||
sa.Column('mail_from', sa.String(length=512), nullable=False),
|
||||
sa.Column('rcpt_to', sa.String(length=512), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('ignored_email')
|
||||
# ### end Alembic commands ###
|
|
@ -1,5 +1,5 @@
|
|||
from app.models import User, Alias, AuthorizedAddress
|
||||
from email_handler import get_mailbox_from_mail_from
|
||||
from app.models import User, Alias, AuthorizedAddress, IgnoredEmail
|
||||
from email_handler import get_mailbox_from_mail_from, should_ignore
|
||||
|
||||
|
||||
def test_get_mailbox_from_mail_from(flask_client):
|
||||
|
@ -32,3 +32,11 @@ def test_get_mailbox_from_mail_from(flask_client):
|
|||
)
|
||||
mb = get_mailbox_from_mail_from("unauthorized@gmail.com", alias)
|
||||
assert mb.email == "a@b.c"
|
||||
|
||||
|
||||
def test_should_ignore(flask_client):
|
||||
assert should_ignore("mail_from", []) is False
|
||||
|
||||
assert not should_ignore("mail_from", ["rcpt_to"])
|
||||
IgnoredEmail.create(mail_from="mail_from", rcpt_to="rcpt_to", commit=True)
|
||||
assert should_ignore("mail_from", ["rcpt_to"])
|
||||
|
|
Loading…
Reference in New Issue