python / cpython

The Python programming language
https://www.python.org
Other
62.39k stars 29.96k forks source link

EmailMessage().add_attachment() doesn't work for html files #91863

Open VolodyaCO opened 2 years ago

VolodyaCO commented 2 years ago

Bug report

I am trying to send a 1.5 MB .html file using from email.message import EmailMessage through the add_attachment method. If the filename ends in ".html", the email will not be sent, nor any warning/exception is raised.

This is the code that I am using:

message["From"] = sender_email
message["To"] = ", ".join(receiver_email)
message.set_content(text)

context = ssl.create_default_context()

for i, fn in enumerate([filename, mapname]):
    print("Processing filename", fn)
    with open(fn, "rb") as attachment:
        content = attachment.read()
        ctype, encoding = mimetypes.guess_type(fn)
        maintype, subtype = ctype.split("/", 1)
        message.add_attachment(
            content,
            maintype=maintype,
            subtype=subtype,
            filename=f"{i}_{fn}",
        )

with smtplib.SMTP_SSL("smtp.gmail.com", port, context=context) as server:
    server.login(sender_email, password)
    server.send_message(message)
    print("Sent!")

You see that I have two filenames, one is filename and the other one is mapname. filename is a csv file and mapname is an html file. If I only use the filename, the mail is sent. If I add mapname, the mail is not sent. If I only use mapname, the email is not sent either.

If the filename is changed: f"{i}_{fn.split('.')[0]}", so that the extension is removed, the email is sent! This shows that the HTML is not corrupt, it's just because of the extension! Also, I tried sending a simple html such as this one:

msg_content = """
<html><body>
  Hello world
</body></html>"""
content = bytes(msg_content, "utf-8")
ctype, encoding = mimetypes.guess_type("second.html")
maintype, subtype = ctype.split("/", 1)
message.add_attachment(
    content,
    maintype=maintype,
    subtype=subtype,
    filename="second.html",
)

And it still does not work.

Your environment

I'm using a virtual environment with Python version Python 3.9.10. The architecture is arm64. pip freeze shows:

absl-py==1.0.0
alembic==1.7.6
anyio==3.5.0
appnope==0.1.2
argon2-cffi==21.3.0
argon2-cffi-bindings==21.2.0
asttokens==2.0.5
attrs==21.4.0
autopage==0.5.0
Babel==2.9.1
backcall==0.2.0
beautifulsoup4==4.10.0
beniget==0.4.1
black==22.1.0
bleach==4.1.0
bokeh==2.4.2
certifi==2021.10.8
cffi==1.15.0
charset-normalizer==2.0.12
chex==0.1.1
click==8.0.4
cliff==3.10.1
cmaes==0.8.2
cmd2==2.4.0
colorlog==6.6.0
cycler==0.11.0
Cython==0.29.28
debugpy==1.5.1
decorator==5.1.1
defusedxml==0.7.1
dm-tree==0.1.6
dnspython==2.2.1
entrypoints==0.4
executing==0.8.3
flatbuffers==2.0
flax==0.4.0
fonttools==4.30.0
gast==0.5.3
idna==3.3
ipykernel==6.9.1
ipython==8.1.1
ipython-genutils==0.2.0
jedi==0.18.1
Jinja2==3.1.1
joblib==1.1.0
json5==0.9.6
jsonschema==4.4.0
jupyter-client==7.1.2
jupyter-core==4.9.2
jupyter-server==1.16.0
jupyterlab==3.3.2
jupyterlab-pygments==0.1.2
jupyterlab-server==2.12.0
kiwisolver==1.3.2
lightgbm==3.3.2
Mako==1.2.0
MarkupSafe==2.1.0
matplotlib==3.5.1
matplotlib-inline==0.1.3
miceforest==5.3.0
mistune==0.8.4
msgpack==1.0.3
mypy-extensions==0.4.3
nbclassic==0.3.7
nbclient==0.5.13
nbconvert==6.4.5
nbformat==5.2.0
nest-asyncio==1.5.4
notebook==6.4.10
notebook-shim==0.1.0
numpy==1.22.3
opt-einsum==3.3.0
optax==0.1.1
optuna==2.10.0
packaging==21.3
pandas==1.3.5
pandocfilters==1.5.0
parso==0.8.3
pathspec==0.9.0
pbr==5.8.1
pexpect==4.8.0
pickleshare==0.7.5
Pillow==9.0.1
platformdirs==2.5.1
ply==3.11
prettytable==3.2.0
prometheus-client==0.13.1
prompt-toolkit==3.0.28
ptyprocess==0.7.0
pure-eval==0.2.2
pybind11==2.9.1
pycparser==2.21
Pygments==2.11.2
pymongo==4.0.1
pyparsing==3.0.7
pyperclip==1.8.2
pyrsistent==0.18.1
python-dateutil==2.8.2
pythran==0.11.0
pytz==2021.3
PyYAML==6.0
pyzmq==22.3.0
requests==2.27.1
scipy==1.9.0.dev0+1659.2656ccb
Send2Trash==1.8.0
six==1.16.0
sniffio==1.2.0
soupsieve==2.3.1
SQLAlchemy==1.4.32
stack-data==0.2.0
stevedore==3.5.0
terminado==0.13.3
testpath==0.6.0
threadpoolctl==3.1.0
tomli==2.0.1
toolz==0.11.2
tornado==6.1
tqdm==4.63.0
traitlets==5.1.1
typing_extensions==4.1.1
urllib3==1.26.9
wcwidth==0.2.5
webencodings==0.5.1
websocket-client==1.3.2
eugenetriguba commented 2 years ago

This is a little hard to follow for me and neither of the examples that were provided are complete (able to be run on their own without further modifications). Would you be able to provide the smallest piece of code that reproduces the issue?

VolodyaCO commented 2 years ago

Ok this is an attempt of a somewhat reproducible code:

import smtplib, ssl
import glob
from email.message import EmailMessage
import mimetypes

port = 465  # For SSL
message = EmailMessage()
message["Subject"] = "Some subject"
message["From"] = sender_email
message["To"] = receiver_email
password="your password"

context = ssl.create_default_context()

msg_content = """
<html><body>
  Hello world
</body></html>"""
content = bytes(msg_content, "utf-8")
ctype, encoding = mimetypes.guess_type("second.html")
maintype, subtype = ctype.split("/", 1)
message.add_attachment(
    content,
    maintype=maintype,
    subtype=subtype,
    filename="second.html",
)

with smtplib.SMTP_SSL("smtp.gmail.com", port, context=context) as server:
    server.login(sender_email, password)
    server.send_message(message)
    print("Sent!")

You need to input the sender, receiver and password for gmail.

fsc-eriker commented 12 months ago

Can you show the generated message's as_string() representation, ideally with a diff between a working and a non-working example? Does it work if you hardcode the text/html type instead of having Python guess the type?

codeZeilen commented 2 months ago

The MWE does not produce the described failure, neither for 3.9.10 nor for 3.10.13.

I suggest closing this issue.