4.22.3
This commit is contained in:
parent
5d093db4f6
commit
b643f0644b
@ -21,3 +21,4 @@ repos:
|
|||||||
- id: djlint-jinja
|
- id: djlint-jinja
|
||||||
files: '.*\.html'
|
files: '.*\.html'
|
||||||
entry: djlint --reformat
|
entry: djlint --reformat
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ from attr import dataclass
|
|||||||
from app import config
|
from app import config
|
||||||
from app.email import headers
|
from app.email import headers
|
||||||
from app.log import LOG
|
from app.log import LOG
|
||||||
from app.message_utils import message_to_bytes
|
from app.message_utils import message_to_bytes, message_format_base64_parts
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -173,8 +173,12 @@ class MailSender:
|
|||||||
self._save_request_to_unsent_dir(send_request)
|
self._save_request_to_unsent_dir(send_request)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _save_request_to_unsent_dir(self, send_request: SendRequest):
|
def _save_request_to_unsent_dir(
|
||||||
file_name = f"DeliveryFail-{int(time.time())}-{uuid.uuid4()}.{SendRequest.SAVE_EXTENSION}"
|
self, send_request: SendRequest, prefix: str = "DeliveryFail"
|
||||||
|
):
|
||||||
|
file_name = (
|
||||||
|
f"{prefix}-{int(time.time())}-{uuid.uuid4()}.{SendRequest.SAVE_EXTENSION}"
|
||||||
|
)
|
||||||
file_path = os.path.join(config.SAVE_UNSENT_DIR, file_name)
|
file_path = os.path.join(config.SAVE_UNSENT_DIR, file_name)
|
||||||
file_contents = send_request.to_bytes()
|
file_contents = send_request.to_bytes()
|
||||||
with open(file_path, "wb") as fd:
|
with open(file_path, "wb") as fd:
|
||||||
@ -256,7 +260,7 @@ def sl_sendmail(
|
|||||||
send_request = SendRequest(
|
send_request = SendRequest(
|
||||||
envelope_from,
|
envelope_from,
|
||||||
envelope_to,
|
envelope_to,
|
||||||
msg,
|
message_format_base64_parts(msg),
|
||||||
mail_options,
|
mail_options,
|
||||||
rcpt_options,
|
rcpt_options,
|
||||||
is_forward,
|
is_forward,
|
||||||
|
@ -1,21 +1,42 @@
|
|||||||
|
import re
|
||||||
from email import policy
|
from email import policy
|
||||||
from email.message import Message
|
from email.message import Message
|
||||||
|
|
||||||
|
from app.email import headers
|
||||||
from app.log import LOG
|
from app.log import LOG
|
||||||
|
|
||||||
|
# Spam assassin might flag as spam with a different line length
|
||||||
|
BASE64_LINELENGTH = 76
|
||||||
|
|
||||||
|
|
||||||
def message_to_bytes(msg: Message) -> bytes:
|
def message_to_bytes(msg: Message) -> bytes:
|
||||||
"""replace Message.as_bytes() method by trying different policies"""
|
"""replace Message.as_bytes() method by trying different policies"""
|
||||||
for generator_policy in [None, policy.SMTP, policy.SMTPUTF8]:
|
for generator_policy in [None, policy.SMTP, policy.SMTPUTF8]:
|
||||||
try:
|
try:
|
||||||
return msg.as_bytes(policy=generator_policy)
|
return msg.as_bytes(policy=generator_policy)
|
||||||
except:
|
except Exception:
|
||||||
LOG.w("as_bytes() fails with %s policy", policy, exc_info=True)
|
LOG.w("as_bytes() fails with %s policy", policy, exc_info=True)
|
||||||
|
|
||||||
msg_string = msg.as_string()
|
msg_string = msg.as_string()
|
||||||
try:
|
try:
|
||||||
return msg_string.encode()
|
return msg_string.encode()
|
||||||
except:
|
except Exception:
|
||||||
LOG.w("as_string().encode() fails", exc_info=True)
|
LOG.w("as_string().encode() fails", exc_info=True)
|
||||||
|
|
||||||
return msg_string.encode(errors="replace")
|
return msg_string.encode(errors="replace")
|
||||||
|
|
||||||
|
|
||||||
|
def message_format_base64_parts(msg: Message) -> Message:
|
||||||
|
for part in msg.walk():
|
||||||
|
if part.get(
|
||||||
|
headers.CONTENT_TRANSFER_ENCODING
|
||||||
|
) == "base64" and part.get_content_type() in ("text/plain", "text/html"):
|
||||||
|
# Remove line breaks
|
||||||
|
body = re.sub("[\r\n]", "", part.get_payload())
|
||||||
|
# Split in 80 column lines
|
||||||
|
chunks = [
|
||||||
|
body[i : i + BASE64_LINELENGTH]
|
||||||
|
for i in range(0, len(body), BASE64_LINELENGTH)
|
||||||
|
]
|
||||||
|
part.set_payload("\r\n".join(chunks))
|
||||||
|
return msg
|
||||||
|
@ -50,7 +50,9 @@
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
This Youtube video can also quickly walk you through the steps:
|
This Youtube video can also quickly walk you through the steps:
|
||||||
<a href="https://www.youtube.com/watch?v=VsypF-DBaow" target="_blank">
|
<a href="https://www.youtube.com/watch?v=VsypF-DBaow"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
How to send emails from an alias <i class="fe fe-external-link"></i>
|
How to send emails from an alias <i class="fe fe-external-link"></i>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -23,7 +23,9 @@
|
|||||||
|
|
||||||
<div class="alert alert-danger" role="alert">
|
<div class="alert alert-danger" role="alert">
|
||||||
This feature is only available on Premium plan.
|
This feature is only available on Premium plan.
|
||||||
<a href="{{ URL }}/dashboard/pricing" target="_blank" rel="noopener">
|
<a href="{{ URL }}/dashboard/pricing"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
Upgrade<i class="fe fe-external-link"></i>
|
Upgrade<i class="fe fe-external-link"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,7 +78,7 @@
|
|||||||
data-clipboard-text=".*suffix">.*suffix</em>
|
data-clipboard-text=".*suffix">.*suffix</em>
|
||||||
<br />
|
<br />
|
||||||
To test out regex, we recommend using regex tester tool like
|
To test out regex, we recommend using regex tester tool like
|
||||||
<a href="https://regex101.com" target="_blank">https://regex101.com↗</a>
|
<a href="https://regex101.com" target="_blank" rel="noopener noreferrer">https://regex101.com↗</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -158,7 +158,7 @@
|
|||||||
SPF
|
SPF
|
||||||
<a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework"
|
<a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener">(Wikipedia↗)</a>
|
rel="noopener noreferrer">(Wikipedia↗)</a>
|
||||||
is an email
|
is an email
|
||||||
authentication method
|
authentication method
|
||||||
designed to detect forging sender addresses during the delivery of the email.
|
designed to detect forging sender addresses during the delivery of the email.
|
||||||
@ -229,7 +229,7 @@
|
|||||||
DKIM
|
DKIM
|
||||||
<a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail"
|
<a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener">(Wikipedia↗)</a>
|
rel="noopener noreferrer">(Wikipedia↗)</a>
|
||||||
is an
|
is an
|
||||||
email
|
email
|
||||||
authentication method
|
authentication method
|
||||||
@ -335,7 +335,7 @@
|
|||||||
DMARC
|
DMARC
|
||||||
<a href="https://en.wikipedia.org/wiki/DMARC"
|
<a href="https://en.wikipedia.org/wiki/DMARC"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener">
|
rel="noopener noreferrer">
|
||||||
(Wikipedia↗)
|
(Wikipedia↗)
|
||||||
</a>
|
</a>
|
||||||
is designed to protect the domain from unauthorized use, commonly known as email spoofing.
|
is designed to protect the domain from unauthorized use, commonly known as email spoofing.
|
||||||
|
@ -72,7 +72,7 @@ PGP Encryption
|
|||||||
</ul>
|
</ul>
|
||||||
<div class="small-text">
|
<div class="small-text">
|
||||||
More information on our
|
More information on our
|
||||||
<a href="https://simplelogin.io/pricing" target="_blank" rel="noopener">
|
<a href="https://simplelogin.io/pricing" target="_blank" rel="noopener noreferrer">
|
||||||
Pricing
|
Pricing
|
||||||
Page <i class="fe fe-external-link"></i>
|
Page <i class="fe fe-external-link"></i>
|
||||||
</a>
|
</a>
|
||||||
@ -120,7 +120,7 @@ Upgrade your SimpleLogin account
|
|||||||
<div id="normal-upgrade" class="{% if proton_upgrade %} collapse{% endif %}">
|
<div id="normal-upgrade" class="{% if proton_upgrade %} collapse{% endif %}">
|
||||||
<div class="display-6 my-3">
|
<div class="display-6 my-3">
|
||||||
🔐 Secure payments by
|
🔐 Secure payments by
|
||||||
<a href="https://paddle.com" target="_blank" rel="noopener">
|
<a href="https://paddle.com" target="_blank" rel="noopener noreferrer">
|
||||||
Paddle <i class="fe fe-external-link"></i>
|
Paddle <i class="fe fe-external-link"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -164,13 +164,13 @@ $4/month
|
|||||||
<hr />
|
<hr />
|
||||||
<i class="fa fa-bitcoin"></i>
|
<i class="fa fa-bitcoin"></i>
|
||||||
Payment via
|
Payment via
|
||||||
<a href="https://commerce.coinbase.com/?lang=en" target="_blank">
|
<a href="https://commerce.coinbase.com/?lang=en" target="_blank" rel="noopener noreferrer">
|
||||||
Coinbase Commerce<i class="fe fe-external-link"></i>
|
Coinbase Commerce<i class="fe fe-external-link"></i>
|
||||||
</a>
|
</a>
|
||||||
<br />
|
<br />
|
||||||
Currently Bitcoin, Bitcoin Cash, Dai, Ethereum, Litecoin and USD Coin are supported.
|
Currently Bitcoin, Bitcoin Cash, Dai, Ethereum, Litecoin and USD Coin are supported.
|
||||||
<br />
|
<br />
|
||||||
<a class="btn btn-outline-primary" href="{{ url_for('dashboard.coinbase_checkout_route') }}" target="_blank">
|
<a class="btn btn-outline-primary" href="{{ url_for('dashboard.coinbase_checkout_route') }}" target="_blank" rel="noopener noreferrer">
|
||||||
Yearly billing - Crypto
|
Yearly billing - Crypto
|
||||||
<br />
|
<br />
|
||||||
$30/year
|
$30/year
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
<div class="alert alert-info">
|
<div class="alert alert-info">
|
||||||
This page shows all emails that are either refused by your mailbox (bounced) or detected as spams/phishing (quarantine) via our
|
This page shows all emails that are either refused by your mailbox (bounced) or detected as spams/phishing (quarantine) via our
|
||||||
<a href="https://simplelogin.io/docs/getting-started/anti-phishing/"
|
<a href="https://simplelogin.io/docs/getting-started/anti-phishing/"
|
||||||
target="_blank">anti-phishing program ↗</a>
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">anti-phishing program ↗</a>
|
||||||
<ul class="p-4 mb-0">
|
<ul class="p-4 mb-0">
|
||||||
<li>
|
<li>
|
||||||
If the email is indeed spam, this means the alias is now in the hands of a spammer,
|
If the email is indeed spam, this means the alias is now in the hands of a spammer,
|
||||||
@ -26,7 +27,8 @@
|
|||||||
<li>
|
<li>
|
||||||
If the email isn't spam and your mailbox refuses the email, we recommend to create a <b>filter</b> to avoid your mailbox provider from blocking legitimate emails. Please refer to
|
If the email isn't spam and your mailbox refuses the email, we recommend to create a <b>filter</b> to avoid your mailbox provider from blocking legitimate emails. Please refer to
|
||||||
<a href="https://simplelogin.io/docs/getting-started/troubleshooting/#emails-end-up-in-spam"
|
<a href="https://simplelogin.io/docs/getting-started/troubleshooting/#emails-end-up-in-spam"
|
||||||
target="_blank">Setting up filter for SimpleLogin emails ↗</a>
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">Setting up filter for SimpleLogin emails ↗</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
If the email is flagged as spams/phishing, this means that the sender explicitly states their emails should respect
|
If the email is flagged as spams/phishing, this means that the sender explicitly states their emails should respect
|
||||||
|
@ -73,7 +73,8 @@
|
|||||||
Yearly plan subscribed with cryptocurrency which expires on
|
Yearly plan subscribed with cryptocurrency which expires on
|
||||||
{{ coinbase_sub.end_at.format("YYYY-MM-DD") }}.
|
{{ coinbase_sub.end_at.format("YYYY-MM-DD") }}.
|
||||||
<a href="{{ url_for('dashboard.coinbase_checkout_route') }}"
|
<a href="{{ url_for('dashboard.coinbase_checkout_route') }}"
|
||||||
target="_blank">
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
Extend Subscription <i class="fe fe-external-link"></i>
|
Extend Subscription <i class="fe fe-external-link"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
This feature is only available on Premium plan.
|
This feature is only available on Premium plan.
|
||||||
<a href="{{ url_for('dashboard.pricing') }}"
|
<a href="{{ url_for('dashboard.pricing') }}"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener">
|
rel="noopener noreferrer">
|
||||||
Upgrade<i class="fe fe-external-link"></i>
|
Upgrade<i class="fe fe-external-link"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<a href="https://docs.simplelogin.io"
|
<a href="https://docs.simplelogin.io"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
class="btn btn-block btn-secondary mt-4">
|
class="btn btn-block btn-secondary mt-4">
|
||||||
Documentation <i class="fe fe-external-link"></i>
|
Documentation <i class="fe fe-external-link"></i>
|
||||||
</a>
|
</a>
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
<h4 class="alert-heading">Well done!</h4>
|
<h4 class="alert-heading">Well done!</h4>
|
||||||
<p>
|
<p>
|
||||||
Please head to our
|
Please head to our
|
||||||
<a href="https://docs.simplelogin.io" target="_blank" rel="noopener">
|
<a href="https://docs.simplelogin.io"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
documentation <i class="fe fe-external-link"></i>
|
documentation <i class="fe fe-external-link"></i>
|
||||||
</a>
|
</a>
|
||||||
to see how to add SIWSL into your app.
|
to see how to add SIWSL into your app.
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
<a href="{{ url_for('developer.new_client') }}" class="btn btn-primary">New website</a>
|
<a href="{{ url_for('developer.new_client') }}" class="btn btn-primary">New website</a>
|
||||||
<a href="https://docs.simplelogin.io"
|
<a href="https://docs.simplelogin.io"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
class="ml-2 btn btn-secondary">
|
class="ml-2 btn btn-secondary">
|
||||||
Docs <i class="fe fe-external-link"></i>
|
Docs <i class="fe fe-external-link"></i>
|
||||||
</a>
|
</a>
|
||||||
|
@ -13,7 +13,9 @@
|
|||||||
|
|
||||||
<div class="col-sm-4 col-xl-2">
|
<div class="col-sm-4 col-xl-2">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<a href="{{ client.home_url }}" target="_blank" rel="noopener">
|
<a href="{{ client.home_url }}"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
<img class="card-img-top" src="{{ client.get_icon_url() }}">
|
<img class="card-img-top" src="{{ client.get_icon_url() }}">
|
||||||
</a>
|
</a>
|
||||||
<div class="card-body d-flex flex-column">
|
<div class="card-body d-flex flex-column">
|
||||||
|
@ -46,7 +46,7 @@ https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design -->
|
|||||||
<a href="{{ link }}"
|
<a href="{{ link }}"
|
||||||
class="f-fallback button"
|
class="f-fallback button"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener"
|
rel="noopener noreferrer"
|
||||||
style="color: #FFF;
|
style="color: #FFF;
|
||||||
border-color: #3869d4;
|
border-color: #3869d4;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
|
@ -145,28 +145,28 @@
|
|||||||
<ul class="list-group list-group-transparent list-group-white list-group-flush list-group-borderless mb-0 footer-list-group">
|
<ul class="list-group list-group-transparent list-group-white list-group-flush list-group-borderless mb-0 footer-list-group">
|
||||||
<li>
|
<li>
|
||||||
<a class="list-group-item text-white footer-item "
|
<a class="list-group-item text-white footer-item "
|
||||||
rel="noopener"
|
rel="noopener noreferrer"
|
||||||
href="https://chrome.google.com/webstore/detail/dphilobhebphkdjbpfohgikllaljmgbn">
|
href="https://chrome.google.com/webstore/detail/dphilobhebphkdjbpfohgikllaljmgbn">
|
||||||
Chrome Extension
|
Chrome Extension
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="list-group-item text-white footer-item "
|
<a class="list-group-item text-white footer-item "
|
||||||
rel="noopener"
|
rel="noopener noreferrer"
|
||||||
href="https://addons.mozilla.org/firefox/addon/simplelogin/">
|
href="https://addons.mozilla.org/firefox/addon/simplelogin/">
|
||||||
Firefox Add-on
|
Firefox Add-on
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="list-group-item text-white footer-item "
|
<a class="list-group-item text-white footer-item "
|
||||||
rel="noopener"
|
rel="noopener noreferrer"
|
||||||
href="https://microsoftedge.microsoft.com/addons/detail/simpleloginreceive-sen/diacfpipniklenphgljfkmhinphjlfff">
|
href="https://microsoftedge.microsoft.com/addons/detail/simpleloginreceive-sen/diacfpipniklenphgljfkmhinphjlfff">
|
||||||
Edge Add-on
|
Edge Add-on
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="list-group-item text-white footer-item "
|
<a class="list-group-item text-white footer-item "
|
||||||
rel="noopener"
|
rel="noopener noreferrer"
|
||||||
href="https://apps.apple.com/app/id1494051017">
|
href="https://apps.apple.com/app/id1494051017">
|
||||||
Safari
|
Safari
|
||||||
Extension
|
Extension
|
||||||
@ -174,7 +174,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="list-group-item text-white footer-item "
|
<a class="list-group-item text-white footer-item "
|
||||||
rel="noopener"
|
rel="noopener noreferrer"
|
||||||
href="https://apps.apple.com/app/id1494359858">
|
href="https://apps.apple.com/app/id1494359858">
|
||||||
iOS
|
iOS
|
||||||
(App Store)
|
(App Store)
|
||||||
@ -182,14 +182,14 @@
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="list-group-item text-white footer-item "
|
<a class="list-group-item text-white footer-item "
|
||||||
rel="noopener"
|
rel="noopener noreferrer"
|
||||||
href="https://play.google.com/store/apps/details?id=io.simplelogin.android">
|
href="https://play.google.com/store/apps/details?id=io.simplelogin.android">
|
||||||
Android (Play Store)
|
Android (Play Store)
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="list-group-item text-white footer-item "
|
<a class="list-group-item text-white footer-item "
|
||||||
rel="noopener"
|
rel="noopener noreferrer"
|
||||||
href="https://f-droid.org/en/packages/io.simplelogin.android.fdroid/">
|
href="https://f-droid.org/en/packages/io.simplelogin.android.fdroid/">
|
||||||
Android (F-Droid)
|
Android (F-Droid)
|
||||||
</a>
|
</a>
|
||||||
|
@ -75,14 +75,17 @@
|
|||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Help</a>
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Help</a>
|
||||||
<div class="dropdown-menu dropdown-menu-left dropdown-menu-arrow">
|
<div class="dropdown-menu dropdown-menu-left dropdown-menu-arrow">
|
||||||
<div class="dropdown-item">
|
<div class="dropdown-item">
|
||||||
<a href="https://simplelogin.io/docs/" target="_blank">
|
<a href="https://simplelogin.io/docs/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
Docs
|
Docs
|
||||||
<i class="fa fa-external-link" aria-hidden="true"></i>
|
<i class="fa fa-external-link" aria-hidden="true"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown-item">
|
<div class="dropdown-item">
|
||||||
<a href="https://github.com/simple-login/app/discussions"
|
<a href="https://github.com/simple-login/app/discussions"
|
||||||
target="_blank">
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
Forum
|
Forum
|
||||||
<i class="fa fa-external-link" aria-hidden="true"></i>
|
<i class="fa fa-external-link" aria-hidden="true"></i>
|
||||||
</a>
|
</a>
|
||||||
@ -94,7 +97,9 @@
|
|||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="nav-item">
|
<div class="nav-item">
|
||||||
<a href="https://simplelogin.io/docs/" target="_blank">
|
<a href="https://simplelogin.io/docs/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
Docs
|
Docs
|
||||||
<i class="fa fa-external-link" aria-hidden="true"></i>
|
<i class="fa fa-external-link" aria-hidden="true"></i>
|
||||||
</a>
|
</a>
|
||||||
|
@ -98,14 +98,17 @@
|
|||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Help</a>
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Help</a>
|
||||||
<div class="dropdown-menu dropdown-menu-left dropdown-menu-arrow">
|
<div class="dropdown-menu dropdown-menu-left dropdown-menu-arrow">
|
||||||
<div class="dropdown-item">
|
<div class="dropdown-item">
|
||||||
<a href="https://simplelogin.io/docs/" target="_blank">
|
<a href="https://simplelogin.io/docs/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
Docs
|
Docs
|
||||||
<i class="fa fa-external-link" aria-hidden="true"></i>
|
<i class="fa fa-external-link" aria-hidden="true"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown-item">
|
<div class="dropdown-item">
|
||||||
<a href="https://github.com/simple-login/app/discussions"
|
<a href="https://github.com/simple-login/app/discussions"
|
||||||
target="_blank">
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
Forum
|
Forum
|
||||||
<i class="fa fa-external-link" aria-hidden="true"></i>
|
<i class="fa fa-external-link" aria-hidden="true"></i>
|
||||||
</a>
|
</a>
|
||||||
|
39
app/tests/example_emls/bad_base64format.eml
Normal file
39
app/tests/example_emls/bad_base64format.eml
Normal file
File diff suppressed because one or more lines are too long
@ -2,7 +2,8 @@ import email
|
|||||||
from app.email_utils import (
|
from app.email_utils import (
|
||||||
copy,
|
copy,
|
||||||
)
|
)
|
||||||
from app.message_utils import message_to_bytes
|
from app.message_utils import message_to_bytes, message_format_base64_parts
|
||||||
|
from tests.utils import load_eml_file
|
||||||
|
|
||||||
|
|
||||||
def test_copy():
|
def test_copy():
|
||||||
@ -33,3 +34,13 @@ def test_to_bytes():
|
|||||||
|
|
||||||
msg = email.message_from_string("éèà€")
|
msg = email.message_from_string("éèà€")
|
||||||
assert message_to_bytes(msg).decode() == "\néèà€"
|
assert message_to_bytes(msg).decode() == "\néèà€"
|
||||||
|
|
||||||
|
|
||||||
|
def test_base64_line_breaks():
|
||||||
|
msg = load_eml_file("bad_base64format.eml")
|
||||||
|
msg = message_format_base64_parts(msg)
|
||||||
|
for part in msg.walk():
|
||||||
|
if part.get("content-transfer-encoding") == "base64":
|
||||||
|
body = part.get_payload()
|
||||||
|
for line in body.splitlines():
|
||||||
|
assert len(line) <= 76
|
||||||
|
Loading…
x
Reference in New Issue
Block a user