Sign DKIM at app level
- add DKIM_PRIVATE_KEY_PATH param - create email_utils.add_dkim_signature - add DKIM signature for transactional emails - add DKIM signature for forward & reply emails. In reply phase, only non-custom-domain emails have DKIM added.
This commit is contained in:
parent
18751d452b
commit
a61b900675
|
@ -28,12 +28,15 @@ EMAIL_SERVERS_WITH_PRIORITY=[(10, "email.hostname.")]
|
|||
|
||||
# these emails are ignored when computing stats
|
||||
# IGNORED_EMAILS = ["my_email@domain.com"]
|
||||
|
||||
# the DKIM private key used to compute DKIM-Signature
|
||||
DKIM_PRIVATE_KEY_PATH=local_data/dkim.key
|
||||
# <<< END Email related settings >>>
|
||||
|
||||
|
||||
# <<< Database >>>
|
||||
# delete and recreate sqlite database, for local development
|
||||
RESET_DB=true
|
||||
# RESET_DB=true
|
||||
|
||||
# DB Connection
|
||||
DB_URI=sqlite:///db.sqlite
|
||||
|
|
|
@ -57,6 +57,14 @@ if os.environ.get("IGNORED_EMAILS"):
|
|||
else:
|
||||
IGNORED_EMAILS = []
|
||||
|
||||
DKIM_PRIVATE_KEY_PATH = get_abs_path(os.environ["DKIM_PRIVATE_KEY_PATH"])
|
||||
DKIM_SELECTOR = b"dkim"
|
||||
|
||||
with open(DKIM_PRIVATE_KEY_PATH) as f:
|
||||
DKIM_PRIVATE_KEY = f.read()
|
||||
|
||||
DKIM_HEADERS = [b'from', b'to', b'subject']
|
||||
|
||||
# Database
|
||||
DB_URI = os.environ["DB_URI"]
|
||||
|
||||
|
|
|
@ -3,9 +3,18 @@ from email.message import EmailMessage
|
|||
from email.utils import make_msgid, formatdate
|
||||
from smtplib import SMTP
|
||||
|
||||
import dkim
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
from app.config import SUPPORT_EMAIL, ROOT_DIR, POSTFIX_SERVER, NOT_SEND_EMAIL
|
||||
from app.config import (
|
||||
SUPPORT_EMAIL,
|
||||
ROOT_DIR,
|
||||
POSTFIX_SERVER,
|
||||
NOT_SEND_EMAIL,
|
||||
DKIM_SELECTOR,
|
||||
DKIM_PRIVATE_KEY,
|
||||
DKIM_HEADERS,
|
||||
)
|
||||
from app.log import LOG
|
||||
|
||||
|
||||
|
@ -123,7 +132,12 @@ def send_email(to_email, subject, plaintext, html):
|
|||
LOG.d("Date header: %s", date_header)
|
||||
msg["Date"] = date_header
|
||||
|
||||
smtp.send_message(msg, from_addr=SUPPORT_EMAIL, to_addrs=[to_email])
|
||||
# add DKIM
|
||||
email_domain = SUPPORT_EMAIL[SUPPORT_EMAIL.find("@") + 1 :]
|
||||
add_dkim_signature(msg, email_domain)
|
||||
|
||||
msg_raw = msg.as_string().encode()
|
||||
smtp.sendmail(SUPPORT_EMAIL, to_email, msg_raw)
|
||||
|
||||
|
||||
def get_email_name(email_from):
|
||||
|
@ -146,3 +160,22 @@ def get_email_part(email_from):
|
|||
return email_from[email_from.find("<") + 1 : email_from.find(">")].strip()
|
||||
|
||||
return email_from
|
||||
|
||||
|
||||
def add_dkim_signature(msg: EmailMessage, email_domain: str):
|
||||
# Specify headers in "byte" form
|
||||
# Generate message signature
|
||||
sig = dkim.sign(
|
||||
msg.as_string().encode(),
|
||||
DKIM_SELECTOR,
|
||||
email_domain.encode(),
|
||||
DKIM_PRIVATE_KEY.encode(),
|
||||
include_headers=DKIM_HEADERS,
|
||||
)
|
||||
sig = sig.decode()
|
||||
|
||||
# remove linebreaks from sig
|
||||
sig = sig.replace("\n", " ").replace("\r", "")
|
||||
|
||||
# Add the DKIM-Signature
|
||||
msg.add_header("DKIM-Signature", sig[len("DKIM-Signature: ") :])
|
||||
|
|
|
@ -39,7 +39,12 @@ from smtplib import SMTP
|
|||
from aiosmtpd.controller import Controller
|
||||
|
||||
from app.config import EMAIL_DOMAIN, POSTFIX_SERVER, URL
|
||||
from app.email_utils import get_email_name, get_email_part, send_email
|
||||
from app.email_utils import (
|
||||
get_email_name,
|
||||
get_email_part,
|
||||
send_email,
|
||||
add_dkim_signature,
|
||||
)
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import GenEmail, ForwardEmail, ForwardEmailLog
|
||||
|
@ -179,6 +184,8 @@ class MailHandler:
|
|||
envelope.rcpt_options,
|
||||
)
|
||||
|
||||
add_dkim_signature(msg, EMAIL_DOMAIN)
|
||||
|
||||
# smtp.send_message has UnicodeEncodeErroremail issue
|
||||
# encode message raw directly instead
|
||||
msg_raw = msg.as_string().encode()
|
||||
|
@ -242,6 +249,10 @@ class MailHandler:
|
|||
)
|
||||
del msg["DKIM-Signature"]
|
||||
|
||||
# add DKIM-Signature for non-custom-domain alias
|
||||
if alias.endswith(EMAIL_DOMAIN):
|
||||
add_dkim_signature(msg, EMAIL_DOMAIN)
|
||||
|
||||
# email seems to come from alias
|
||||
msg.replace_header("From", alias)
|
||||
msg.replace_header("To", forward_email.website_email)
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXAIBAAKBgQCxhcKgFHz+HbZiuUhH7iGCVsaZYQ7xzf64ui+09QFlSYzl7d28
|
||||
LVlr7nvM0+xDbwwsgu2D1vweklroWM5FjbfVtJX3HvSnNbwceX5du/m8RHelmX0/
|
||||
vLSfsEcnvdNjBmwl/gSIUb660pEp2yo6dUBDTzTDUBNoL6qmnnTNhriRoQIDAQAB
|
||||
AoGAdhGEtHtr9odEerzIei7DUrDsPa70BZcAR1Rtzmj1mKwmbfaad0GiK8rdxAlf
|
||||
JiqBaklaN0mRPbQRil8mMdRj4z8gBYbiHWIL7q6zEjjo8f6CUnNqKgs2trTApqLq
|
||||
L4l110fFSHCmIava5Ly9hJhdOWuJ+PUbcbp0l3j2yoz7RhECQQDa8IMEB/qqeM+e
|
||||
FTz2+F3HhPI3tGALKWYyCbqcip9UUePfPQ/m547YXsdc1ATzb8OsI7emqTcZLu7H
|
||||
joX+8WN/AkEAz5J9uFnp2+fWvmkNV1imoys38OwOq7yYUBSfgDymuzWrf8D2L5mt
|
||||
gSK2LToIjfMRwdJ1RFLGv6oCy6ge3aga3wJAaEKKkZvfIdkgPY6tloqV1hKYajCK
|
||||
YCZZ1VBOvodA8p2An2lrrjDtFFqmI62PogHCM7JanZINe/+elAdqBgsbrwJBAIN1
|
||||
wY2Z1FRjlkttePeSu6anXnyE5B28CbLd/M5YmzgBm6YDbWdkKtCYTUyDbpuID/zy
|
||||
7zXgPuNwJukYhsPXDX0CQGD3laRUSRZiVSD/rJwsJTG2o1FZcsv13CO/0jY7sYxk
|
||||
IjBK29XMHhTB/dip+beU0RCLFjB3nNK8VyMWmmn1WJ0=
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -10,6 +10,7 @@ ADMIN_EMAIL=to_fill
|
|||
# Max number emails user can generate for free plan
|
||||
MAX_NB_EMAIL_FREE_PLAN=3
|
||||
EMAIL_SERVERS_WITH_PRIORITY=[(10, "email.hostname.")]
|
||||
DKIM_PRIVATE_KEY_PATH=local_data/dkim.key
|
||||
|
||||
# Database
|
||||
RESET_DB=true
|
||||
|
|
Loading…
Reference in New Issue