Merge pull request #112 from simple-login/fix-email

Fix email To header
This commit is contained in:
Son Nguyen Kim 2020-03-15 23:18:00 +01:00 committed by GitHub
commit f049960c81
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 30 additions and 78 deletions

View file

@ -1,26 +1,18 @@
from email.utils import parseaddr
from flask import g
from flask import jsonify, request
from flask import jsonify
from flask import request
from flask_cors import cross_origin
from app.api.base import api_bp, verify_api_key
from app.config import EMAIL_DOMAIN
from app.config import PAGE_LIMIT
from app.dashboard.views.alias_log import get_alias_log
from app.dashboard.views.index import get_alias_info, AliasInfo
from app.extensions import db
from app.models import GenEmail, ForwardEmail, ForwardEmailLog
from app.utils import random_string
import re
from flask import render_template, request, redirect, url_for, flash
from flask_login import login_required, current_user
from flask_wtf import FlaskForm
from wtforms import StringField, validators, ValidationError
from app.config import EMAIL_DOMAIN
from app.dashboard.base import dashboard_bp
from app.email_utils import get_email_part
from app.extensions import db
from app.log import LOG
from app.models import ForwardEmailLog
from app.models import GenEmail, ForwardEmail
from app.utils import random_string
@ -310,7 +302,7 @@ def create_contact_route(alias_id):
if not ForwardEmail.get_by(reply_email=reply_email):
break
website_email = get_email_part(contact_email)
_, website_email = parseaddr(contact_email)
# already been added
if ForwardEmail.get_by(gen_email_id=gen_email.id, website_email=website_email):

View file

@ -1,4 +1,5 @@
import re
from email.utils import parseaddr
from flask import render_template, request, redirect, url_for, flash
from flask_login import login_required, current_user
@ -7,7 +8,6 @@ from wtforms import StringField, validators, ValidationError
from app.config import EMAIL_DOMAIN
from app.dashboard.base import dashboard_bp
from app.email_utils import get_email_part
from app.extensions import db
from app.log import LOG
from app.models import GenEmail, ForwardEmail
@ -76,7 +76,7 @@ def alias_contact_manager(alias_id, forward_email_id=None):
if not ForwardEmail.get_by(reply_email=reply_email):
break
website_email = get_email_part(contact_email)
_, website_email = parseaddr(contact_email)
# already been added
if ForwardEmail.get_by(

View file

@ -1,7 +1,5 @@
import email
import os
from email.message import EmailMessage, Message
from email.mime.application import MIMEApplication
from email.message import Message
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
@ -233,28 +231,6 @@ def send_email(
smtp.sendmail(SUPPORT_EMAIL, to_email, msg_raw)
def get_email_name(email_from):
"""parse email from header and return the name part
First Last <ab@cd.com> -> First Last
ab@cd.com -> ""
"""
if "<" in email_from:
return email_from[: email_from.find("<")].strip()
return ""
def get_email_part(email_from):
"""parse email from header and return the email part
First Last <ab@cd.com> -> ab@cd.com
ab@cd.com -> ""
"""
if "<" in email_from:
return email_from[email_from.find("<") + 1 : email_from.find(">")].strip()
return email_from
def get_email_local_part(email):
"""
Get the local part from email

View file

@ -1,6 +1,7 @@
import enum
import random
import uuid
from email.utils import parseaddr, formataddr
import arrow
import bcrypt
@ -17,7 +18,6 @@ from app.config import (
AVATAR_URL_EXPIRATION,
JOB_ONBOARDING_1,
)
from app.extensions import db
from app.log import LOG
from app.oauth_models import Scope
@ -729,14 +729,20 @@ class ForwardEmail(db.Model, ModelMixin):
def website_send_to(self):
"""return the email address with name.
to use when user wants to send an email from the alias"""
from app.email_utils import get_email_name
name = self.website_email.replace("@", " at ")
if self.website_from:
name = get_email_name(self.website_from)
if name:
return name + " " + self.website_email + f" <{self.reply_email}>"
website_name, _ = parseaddr(self.website_from)
return self.website_email.replace("@", " at ") + f" <{self.reply_email}>"
if website_name:
# remove all double quote
website_name = website_name.replace('"', "")
name = website_name + " | " + name
return f'"{name}" <{self.reply_email}>'
# cannot use formataddr here as this field is for email client, not for MTA
# return formataddr((self.website_email.replace("@", " at "), self.reply_email))
def last_reply(self) -> "ForwardEmailLog":
"""return the most recent reply"""

View file

@ -30,14 +30,15 @@ It should contain the following info:
"""
import uuid
import time
import uuid
from email import encoders
from email.message import Message
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.parser import Parser
from email.policy import SMTPUTF8
from email.utils import parseaddr, formataddr
from io import BytesIO
from smtplib import SMTP
from typing import Optional
@ -53,8 +54,6 @@ from app.config import (
POSTFIX_SUBMISSION_TLS,
)
from app.email_utils import (
get_email_name,
get_email_part,
send_email,
add_dkim_signature,
get_email_domain_part,
@ -214,7 +213,7 @@ def get_or_create_forward_email(
"""
website_from_header can be the full-form email, i.e. "First Last <email@example.com>"
"""
website_email = get_email_part(website_from_header)
_, website_email = parseaddr(website_from_header)
forward_email = ForwardEmail.get_by(
gen_email_id=gen_email.id, website_email=website_email
)
@ -333,13 +332,13 @@ def handle_forward(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str:
# so it can pass DMARC check
# replace the email part in from: header
website_from_header = msg["From"]
website_email = get_email_part(website_from_header)
from_header = (
get_email_name(website_from_header)
+ ("" if get_email_name(website_from_header) == "" else " - ")
website_name, website_email = parseaddr(website_from_header)
new_website_name = (
website_name
+ (" - " if website_name else "")
+ website_email.replace("@", " at ")
+ f" <{forward_email.reply_email}>"
)
from_header = formataddr((new_website_name, forward_email.reply_email))
add_or_replace_header(msg, "From", from_header)
LOG.d("new from header:%s", from_header)

View file

@ -1,9 +1,6 @@
from email.message import EmailMessage
from app.email_utils import (
get_email_name,
get_email_part,
get_email_local_part,
get_email_domain_part,
email_belongs_to_alias_domains,
can_be_used_as_personal_email,
@ -14,24 +11,6 @@ from app.extensions import db
from app.models import User, CustomDomain
def test_get_email_name():
assert get_email_name("First Last <ab@cd.com>") == "First Last"
assert get_email_name("First Last<ab@cd.com>") == "First Last"
assert get_email_name(" First Last <ab@cd.com>") == "First Last"
assert get_email_name("ab@cd.com") == ""
def test_get_email_part():
assert get_email_part("First Last <ab@cd.com>") == "ab@cd.com"
assert get_email_part("First Last<ab@cd.com>") == "ab@cd.com"
assert get_email_part(" First Last <ab@cd.com>") == "ab@cd.com"
assert get_email_part("ab@cd.com") == "ab@cd.com"
def test_get_email_local_part():
assert get_email_local_part("ab@cd.com") == "ab"
def test_get_email_domain_part():
assert get_email_domain_part("ab@cd.com") == "cd.com"