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
|
# these emails are ignored when computing stats
|
||||||
# IGNORED_EMAILS = ["my_email@domain.com"]
|
# 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 >>>
|
# <<< END Email related settings >>>
|
||||||
|
|
||||||
|
|
||||||
# <<< Database >>>
|
# <<< Database >>>
|
||||||
# delete and recreate sqlite database, for local development
|
# delete and recreate sqlite database, for local development
|
||||||
RESET_DB=true
|
# RESET_DB=true
|
||||||
|
|
||||||
# DB Connection
|
# DB Connection
|
||||||
DB_URI=sqlite:///db.sqlite
|
DB_URI=sqlite:///db.sqlite
|
||||||
|
|
|
@ -57,6 +57,14 @@ if os.environ.get("IGNORED_EMAILS"):
|
||||||
else:
|
else:
|
||||||
IGNORED_EMAILS = []
|
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
|
# Database
|
||||||
DB_URI = os.environ["DB_URI"]
|
DB_URI = os.environ["DB_URI"]
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,18 @@ from email.message import EmailMessage
|
||||||
from email.utils import make_msgid, formatdate
|
from email.utils import make_msgid, formatdate
|
||||||
from smtplib import SMTP
|
from smtplib import SMTP
|
||||||
|
|
||||||
|
import dkim
|
||||||
from jinja2 import Environment, FileSystemLoader
|
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
|
from app.log import LOG
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,7 +132,12 @@ def send_email(to_email, subject, plaintext, html):
|
||||||
LOG.d("Date header: %s", date_header)
|
LOG.d("Date header: %s", date_header)
|
||||||
msg["Date"] = 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):
|
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[email_from.find("<") + 1 : email_from.find(">")].strip()
|
||||||
|
|
||||||
return email_from
|
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 aiosmtpd.controller import Controller
|
||||||
|
|
||||||
from app.config import EMAIL_DOMAIN, POSTFIX_SERVER, URL
|
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.extensions import db
|
||||||
from app.log import LOG
|
from app.log import LOG
|
||||||
from app.models import GenEmail, ForwardEmail, ForwardEmailLog
|
from app.models import GenEmail, ForwardEmail, ForwardEmailLog
|
||||||
|
@ -179,6 +184,8 @@ class MailHandler:
|
||||||
envelope.rcpt_options,
|
envelope.rcpt_options,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_dkim_signature(msg, EMAIL_DOMAIN)
|
||||||
|
|
||||||
# smtp.send_message has UnicodeEncodeErroremail issue
|
# smtp.send_message has UnicodeEncodeErroremail issue
|
||||||
# encode message raw directly instead
|
# encode message raw directly instead
|
||||||
msg_raw = msg.as_string().encode()
|
msg_raw = msg.as_string().encode()
|
||||||
|
@ -242,6 +249,10 @@ class MailHandler:
|
||||||
)
|
)
|
||||||
del msg["DKIM-Signature"]
|
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
|
# email seems to come from alias
|
||||||
msg.replace_header("From", alias)
|
msg.replace_header("From", alias)
|
||||||
msg.replace_header("To", forward_email.website_email)
|
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 number emails user can generate for free plan
|
||||||
MAX_NB_EMAIL_FREE_PLAN=3
|
MAX_NB_EMAIL_FREE_PLAN=3
|
||||||
EMAIL_SERVERS_WITH_PRIORITY=[(10, "email.hostname.")]
|
EMAIL_SERVERS_WITH_PRIORITY=[(10, "email.hostname.")]
|
||||||
|
DKIM_PRIVATE_KEY_PATH=local_data/dkim.key
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
RESET_DB=true
|
RESET_DB=true
|
||||||
|
|
Loading…
Reference in New Issue