GithubHelp home page GithubHelp logo

sabuhish / fastapi-mail Goto Github PK

View Code? Open in Web Editor NEW
661.0 13.0 79.0 1.06 MB

Fastapi mail system sending mails(individual, bulk) attachments(individual, bulk)

Home Page: https://sabuhish.github.io/fastapi-mail/

License: MIT License

Python 99.14% HTML 0.37% Makefile 0.49%
fastapi fastapi-mail fastmail

fastapi-mail's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fastapi-mail's Issues

Is it possible to enable DEBUG?

I see attribute MAIL_DEBUG in ConnectionConfig but it not using in code.
How can I print email message to log rather than send to recipients?

Send local attachments

Hello, How can i send files from local directory?
when i give a "./app/files/file.pdf" path, I receive this error:

AttributeError: 'bytes' object has no attribute 'read'

or

attachments field type incorrect, must be UploadFile or path

how to set up anonymous sender?

I was configuring fast-api against an exchange server that allows anonymous user to send email.

with flask-mail, I could achieve it by NOT setting it at all, i.e. comment it out

# app.config['MAIL_USERNAME']
# app.config['MAIL_PASSWORD']

with 'fast-api', doing the same resulting in

Traceback (most recent call last):
  File "main.py", line 4, in <module>
    from routers import mail as mail_api
  File "mail.py", line 36, in <module>
    conf = ConnectionConfig(
  File "lib\site-packages\pydantic\env_settings.py", line 34, in __init__
    super().__init__(
  File "lib\site-packages\pydantic\main.py", line 362, in __init__
    raise validation_error
pydantic.error_wrappers.ValidationError: 2 validation errors for ConnectionConfig
MAIL_USERNAME
  field required (type=value_error.missing)
MAIL_PASSWORD
  field required (type=value_error.missing)

setting them to None yields another error

Traceback (most recent call last):
  File "main.py", line 4, in <module>
    from routers import mail as mail_api
  File "mail.py", line 36, in <module>
    conf = ConnectionConfig(
  File "lib\site-packages\pydantic\env_settings.py", line 34, in __init__
    super().__init__(
  File "lib\site-packages\pydantic\main.py", line 362, in __init__
    raise validation_error
pydantic.error_wrappers.ValidationError: 3 validation errors for ConnectionConfig
MAIL_USERNAME
  none is not an allowed value (type=type_error.none.not_allowed)
MAIL_PASSWORD
  none is not an allowed value (type=type_error.none.not_allowed)

I did not try setting them to empty string, as when I did that to flask-mail, it failed to pass the authentication.

Does fast-api support this anonymous scenario? if so, what the correct setting?

Unable to send mail

My fastapi-mail is not sending an email even if the email, the message is properly formatted.

Here is my env variable

configs = ConnectionConfig(
    MAIL_USERNAME="[email protected]",
    MAIL_FROM="[email protected]",
    MAIL_PASSWORD="my_mail_password",
    MAIL_PORT=587,
    MAIL_SERVER="smtp.gmail.com",
    MAIL_TLS=True,
    MAIL_SSL=False)

Here is my code

Dont go on the code its just for demo

def send_email_verification_mail_without_background_task(subject: str, email_to: str, body: str):
    message = MessageSchema(
        subject=subject,
        recipients=[email_to],
        body=body
    )
    fm = FastMail(configs)
    print("Sendig Mail")
    fm.send_message(message)
    print("Mail Sent")

```@router.post('/send_verification_mail/{user_id}')
def send_verification_mail(user_id: str, db: Session = Depends(get_db)):
    user = user_crud.get_user_from_db_by_id(user_id, db)
    encoded_data = jwt.encode(
        {"user_id": user.public_id, "email": user.email}, "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7", algorithm="HS256")
    send_email_verification_mail_without_background_task(
        "Email Verifcation", "[email protected]", "Hello world")
    return encoded_data

It does not raising any error but it is not sending email and yes allow less secure app is on.
Please tell me where I am doing wron

Customize MIME "From" header

Hi,
Thanks for the great library.
I'm trying to customize how the sender appears in a email client.
I see that the spec supports adding a string before the sender's email address in the 'From' header.
It looks like this library maps the 'From' header directly to the sender's email address without the option to add a string.
In fastmail.py
return await msg._message(self.config.MAIL_USERNAME)
In message.py
line 74
async def _message(self,sender):
self.message["From"] = sender
Do you have plans to add that to this library?
Thanks,
Tim

MessageSchema body can't pass dict

conf` = ConnectionConfig(
MAIL_USERNAME = MAIL_EMAIL,
MAIL_PASSWORD = MAIL_PASSWORD,
MAIL_FROM = MAIL_EMAIL,
MAIL_PORT = MAIL_PORT,
MAIL_SERVER = MAIL_HOST,
MAIL_TLS = True,
MAIL_SSL = False,
USE_CREDENTIALS = True,
TEMPLATE_FOLDER = './templates'
)

body={
'verification_code': inserted_email_invitation['verification_code'],
'register_email_url': email_invitation_link.format(
email=inserted_email_invitation['email'],
verification_code=inserted_email_invitation['verification_code'])}
ms = get_mail_service()
message = MessageSchema(
subject="[OrderAIO] - Register - Verification Code",
recipients=[inserted_email_invitation['email']],
body=body,
subtype='html',
)
background_tasks.add_task(ms.send_message, message, `template_name="verification_email.html")

pydantic.error_wrappers.ValidationError: 2 validation errors for MessageSchema
body
str type expected (type=type_error.str)
body
value is not a valid list (type=type_error.list)

Sending Emails As Html

Fastapi mail does not support sending mail by default. In fact, it seems to only support simple string emails. It is a great library but it can be more feature rich if it supported html emails. In one of my more recent fastapi projects, I worked with html emails. I liked this library so much for how minimalistic it is and how it can take off some extra pieces of code from my projects, but seeing that so far this feature has been integral to all my more recent projects and isn't present here and I thought it only right to make the push.

My Proposition:

Using Jinja2 HTML Templates

The email folder must be present within your application working directory.

In sending HTML emails, the CSS expected by mail servers -outlook, google, etc- must be inline CSS. Fastapi mail passes "body" to the rendered template. In creating the template for emails the dynamic objects should be used with the assumption that the variable is named "body" and that it is a python dict.

check out jinja2 for more details
https://jinja.palletsprojects.com/en/2.11.x/

class EmailSchema(BaseModel):
    email: List[EmailStr]
    body: Dict[str, Any]

conf = ConnectionConfig(
    MAIL_USERNAME = "YourUsername",
    MAIL_PASSWORD = "strong_password",
    MAIL_FROM = "[email protected]",
    MAIL_PORT = 587,
    MAIL_SERVER = "your mail server",
    MAIL_TLS = True,
    MAIL_SSL = False,
    TEMPLATE_FOLDER='./email templates folder'
)


@app.post("/email")
async def send_with_template(email: EmailSchema) -> JSONResponse:

    message = MessageSchema(
        subject="Fastapi-Mail module",
        recipients=email.dict().get("email"),  # List of recipients, as many as you can pass 
        body=email.dict().get("body"),
        subtype="html"
        )

    fm = FastMail(conf)
    await fm.send_message(message, template_name="email_template.html") #optional field template_name is the name of the html file(jinja template) to use from the email template folder
    return JSONResponse(status_code=200, content={"message": "email has been sent"})

The library is fantastic, great job!

Enabling UTF-8

Thanks for the awesome library, it makes emails a little less painful again!

However, I have an issue when my SMTP password contains a currency symbol (โ‚ฌ) which results in the following error:

fastapi_mail.errors.ConnectionErrors: Exception raised 'ascii' codec can't encode character '\u20ac' in position 10: ordinal not in range(128), check your credentials or email service configuration

In "plain" smtplib you would make sure that you enable UTF-8, but how do I tell FastAPI-Mail to handle credentials (and/or even the template) using UTF-8?

Gmail connection using fastapi-mail not working

I have been struggling with send email using this module but even after enabling "LESS SECURE APP" on my gmail account I always get this error: fastapi_mail.errors.ConnectionErrors: Exception
raised Error connecting to smtp.gmail.com on port 587: [Errno 10061] Connect call failed ('74.125.140.109', 587), check your credentials or email service configuration.
I have checked my login detail but all to no avail

` message = MessageSchema(
subject="EasyShopas Account Verification Mail",
recipients=email, # List of recipients, as many as you can pass
body=template,
subtype="html"
)

fm = FastMail(conf)
await fm.send_message(message)

Question: Queuing of bulk messages

Most email providers have a rate limit (eg: SES has a 14 mails per second limit), that MAY get trigerred by the background function.

Is there a way to perhaps "Queue" things up in FastAPI itself, without having to rely on celery/redis? Don't think I'll reach this limit so soon, but you can never be too sure.

What do y'all suggest?

Thanks again, for creating this!

Error TLS

I have new issue, my fastapi_mail version is 1.0.0
python version 3.9.7
a run code example i set :

conf = ConnectionConfig(
MAIL_USERNAME = "[email protected]",
MAIL_PASSWORD = "mypassword",
MAIL_FROM = "[email protected]",
MAIL_PORT = 587,
MAIL_SERVER ="smtp.gmail.com",
MAIL_FROM_NAME = "otp",
MAIL_TLS = True,
MAIL_SSL = False,
USE_CREDENTIALS = True,
VALIDATE_CERTS = True
)

But error :

File "/home/hoanganh/smarthome-server/venv/lib/python3.9/site-packages/fastapi_mail/connection.py", line 63, in _configure_connection
raise ConnectionErrors(
fastapi_mail.errors.ConnectionErrors: Exception raised [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129), check your credentials or email service configuration
Help me, please!

Update from fastapi-mail==0.3.7 to 0.4

HelIo, Hi. I updated requirements.txt from 0.3.7 to 0.4 in my app. And it is not working now with such error.
I'm running in Docker container FROM python:3.
This folder exactly existing.
image
But i try to do set up folder as '/' and it will be some.

[Security] Workflow test-package.yml is using vulnerable action actions/checkout

The workflow test-package.yml is referencing action actions/checkout using references v1. However this reference is missing the commit a6747255bd19d7a757dbdda8c654a9f84db19839 which may contain fix to the some vulnerability.
The vulnerability fix that is missing by actions version could be related to:
(1) CVE fix
(2) upgrade of vulnerable dependency
(3) fix to secret leak and others.
Please consider to update the reference to the action.

Sync version of send_message of fm?

Hi, is there a sync version of send_message?

@app.post("/email")
async def simple_send(email: EmailSchema) -> JSONResponse:
    message = MessageSchema(
        subject="Fastapi-Mail module",
        recipients=email.dict().get("email"), 
        body=html,
        subtype="html"
        )

    fm = FastMail(conf)
    """
    I want a sync version of this method!!
    """
    await fm.send_message(message) 
    return JSONResponse(status_code=200, content={"message": "email has been sent"})

Thanks in advance.

beginners guide

Hey I don't know if it is ok to ask but, I tried to copy the examples and changed them to my own credentials, yet it still doesn't work
can you please put on a beginners guide or something, so it would be easier to access?
Thanks in advance!

validate_path issue for attachments

Hi there, thanks for the great library!
I was running into exceptions when I tried to attach files from an arbitary location in the filesystem.
Is there a reason why validate_path is implemented that way, or would you be willing to accept PRs to modify this behavior?
Thanks!

FastMail send methods use sync code

FastMail send methods use sync code from smtplib inside async functions, so it blocks event loop.
Methods __configure_connection, __send_bulk and __send use sync code.

For instance, this part is from __configure_connection method:

if self._tls:
    session.starttls()

session.ehlo()
session.login(self._email, self._password)
self.session = session

Issue with running the demo code

Hi, thanks for the nice work! I am trying out the demo code to send an email from my gmail to other email address, but having this issue right now, any ideas what could be the reason? Thanks.

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/uvicorn/protocols/http/h11_impl.py", line 394, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/usr/local/lib/python3.7/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/site-packages/fastapi/applications.py", line 190, in __call__
    await super().__call__(scope, receive, send)
  File "/usr/local/lib/python3.7/site-packages/starlette/applications.py", line 111, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/usr/local/lib/python3.7/site-packages/starlette/middleware/errors.py", line 181, in __call__
    raise exc from None
  File "/usr/local/lib/python3.7/site-packages/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "/usr/local/lib/python3.7/site-packages/starlette/exceptions.py", line 82, in __call__
    raise exc from None
  File "/usr/local/lib/python3.7/site-packages/starlette/exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 566, in __call__
    await route.handle(scope, receive, send)
  File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 227, in handle
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/site-packages/starlette/routing.py", line 41, in app
    response = await func(request)
  File "/usr/local/lib/python3.7/site-packages/fastapi/routing.py", line 189, in app
    dependant=dependant, values=values, is_coroutine=is_coroutine
  File "/usr/local/lib/python3.7/site-packages/fastapi/routing.py", line 135, in run_endpoint_function
    return await dependant.call(**values)
  File "./app.py", line 53, in simple_send
    await fm.send_message(message)
  File "/usr/local/lib/python3.7/site-packages/fastapi_mail/fastmail.py", line 88, in send_message
    await session.session.send_message(msg)
  File "/usr/local/lib/python3.7/site-packages/aiosmtplib/smtp.py", line 299, in send_message
    timeout=timeout,
  File "/usr/local/lib/python3.7/site-packages/aiosmtplib/smtp.py", line 179, in sendmail
    raise exc
  File "/usr/local/lib/python3.7/site-packages/aiosmtplib/smtp.py", line 165, in sendmail
    timeout=timeout,
  File "/usr/local/lib/python3.7/site-packages/aiosmtplib/esmtp.py", line 271, in mail
    raise SMTPSenderRefused(response.code, response.message, sender)
aiosmtplib.errors.SMTPSenderRefused: (530, '5.7.0 Authentication Required. Learn more at\n5.7.0  https://support.google.com/mail/?p=WantAuthError mq12sm156656pjb.23 - gsmtp', '[email protected]')

[Question] Gmail "MAIL_USERNAME" ConnectionConfig

How do i use gmail alias with "MAIL_USERNAME"? Using gmail, i keep getting bad credential error.

What i'm trying to achieve is
SportJom [email protected]

but that was not possible if my "MAIL_USERNAME" is not the email address.

For "MAIL_USERNAME" I have to use my full email address as the username. Is this just gmail issue?

path_traversal throwing TemplateFolderDoesNotExist for pyenv virtualenv

I maintain all my python venvs with pyenv and the function 'path_traversal' is throwing an error when it tries to resolve the current config file path so that it can validate (I assume) it's not something malicious.
image

Here, the 2 paths that are checked are always different because my pyenv path is in the global .pyenv folder:
image

Is there a way around this?

Pass context

How i can to pass context dict to template? For use inside as {{varibale}}

Proxy configuration

is it working behind a proxy or do we need to configure additional configuration for using a proxy?

Getting error : MAIL_TLS=True and MAIL_SSL=True

"/usr/local/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
return future.result()
File "/home/iibadmin/srik/mayfastapi/fastapienv/lib/python3.9/site-packages/uvicorn/server.py", line 56, in serve
config.load()
File "/home/iibadmin/srik/mayfastapi/fastapienv/lib/python3.9/site-packages/uvicorn/config.py", line 308, in load
self.loaded_app = import_from_string(self.app)
File "/home/iibadmin/srik/mayfastapi/fastapienv/lib/python3.9/site-packages/uvicorn/importer.py", line 20, in import_from_string
module = importlib.import_module(module_str)
File "/usr/local/lib/python3.9/importlib/init.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "", line 1030, in _gcd_import
File "", line 1007, in _find_and_load
File "", line 986, in _find_and_load_unlocked
File "", line 680, in _load_unlocked
File "", line 786, in exec_module
File "", line 923, in get_code
File "", line 853, in source_to_code
File "", line 228, in _call_with_frames_removed
File "./app.py", line 28
MAIL_TLS = True,
^
SyntaxError: invalid syntax

^CINFO: Stopping reloader process [26613]
(fastapienv) iibadmin@iibadmin-uat-ubuntu:~/srik/mayfastapi/fastapienv$

Mypy Stub file not found

Hi,

Thanks for this package. I use mypy in my development env along with VSCode. After installation I am getting:

Stub file not found for "fastapi_mail"

when I import from fastapi_mail.

Screenshot from 2021-09-09 16-23-22

Screenshot from 2021-09-09 16-23-50

path_traversal with venv

Hello!

I'm using poetry and got an issue with TEMPLATE_FOLDER option with exception TemplateFolderDoesNotExist because it not pass path_traversal check.

After debug I found out that:

  • base = Path(__file__).parent.parent inside path_traversal equals to PosixPath('/Users/netstuff/Sites/mailout/api/.venv/lib/python3.9/site-packages')
  • passed to TEMPLATE_FOLDER path equals to PosixPath('/Users/netstuff/Sites/mailout/api/src/mailout/templates/mail')

What can I do with it?
Thank you.

SMTP Relay doesn't Work

I try to connect to a SMTP Relay server without MAIL_PASSWORD, then authentication fails and throws an Exception:

python Exception raised {error}, check your credentials or email service configuration

This is presumably because it requires the username and password when authenticating, but for SMTP Relay it is not required both.

trying to connect with flag SUPPRESS_SEND=1

I noticed if set SUPPRESS_SEND=1 and trying to call

fm = FastMail(settings.email_config)
fm.config.SUPPRESS_SEND = 1
fm.send_message(schema)

so under the hood its work like this

async with Connection(self.config) as session:
    if not self.config.SUPPRESS_SEND:
        await session.session.send_message(msg)

In theory, it may work correctly and is useful, but in practice gitlab CI pytest pipelines can't even open a session and this code crashes with error ConnectionErrors.
I wanna not even open the connection when SUPPRESS_SEND = 1 is specified.

SMTPServerDisconnected

I'm having trouble sending emails from my web service hosted on Digital Ocean, while everything works fine from my local machine.

The full traceback is the following:

Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/uvicorn/protocols/http/httptools_impl.py", line 385, in run_asgi
    result = await app(self.scope, self.receive, self.send)
File "/usr/lib/python3/dist-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
File "/home/mattia/.local/lib/python3.8/site-packages/fastapi/applications.py", line 199, in __call__
     await super().__call__(scope, receive, send)
File "/home/mattia/.local/lib/python3.8/site-packages/starlette/applications.py", line 111, in __call__
     await self.middleware_stack(scope, receive, send)
File "/home/mattia/.local/lib/python3.8/site-packages/starlette/middleware/errors.py", line 181, in __call__
     raise exc from None
File "/home/mattia/.local/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in __call__
     await self.app(scope, receive, _send)
File "/home/mattia/.local/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in __call__
     raise exc from None
File "/home/mattia/.local/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in __call__
     await self.app(scope, receive, sender)
File "/home/mattia/.local/lib/python3.8/site-packages/starlette/routing.py", line 566, in __call__
     await route.handle(scope, receive, send)
File "/home/mattia/.local/lib/python3.8/site-packages/starlette/routing.py", line 227, in handle
     await self.app(scope, receive, send)
File "/home/mattia/.local/lib/python3.8/site-packages/starlette/routing.py", line 41, in app
     response = await func(request)
File "/home/mattia/.local/lib/python3.8/site-packages/fastapi/routing.py", line 201, in app
     raw_response = await run_endpoint_function(
File "/home/mattia/.local/lib/python3.8/site-packages/fastapi/routing.py", line 148, in run_endpoint_function
     return await dependant.call(**values)
File "./app/routers/users.py", line 98, in send_validation_email
     await fm.send_message(message)
File "/home/mattia/.local/lib/python3.8/site-packages/fastapi_mail/fastmail.py", line 92, in send_message
     email_dispatched.send(msg)
File "/home/mattia/.local/lib/python3.8/site-packages/fastapi_mail/connection.py", line 30, in __aexit__
     await self.session.quit()
File "/home/mattia/.local/lib/python3.8/site-packages/aiosmtplib/esmtp.py", line 236, in quit
     response = await self.execute_command(b"QUIT", timeout=timeout)
File "/home/mattia/.local/lib/python3.8/site-packages/aiosmtplib/connection.py", line 420, in execute_command
     response = await self.protocol.execute_command(*args, timeout=timeout)
File "/home/mattia/.local/lib/python3.8/site-packages/aiosmtplib/protocol.py", line 290, in execute_command
     self.write(command)
File "/home/mattia/.local/lib/python3.8/site-packages/aiosmtplib/protocol.py", line 274, in write
     raise SMTPServerDisconnected("Connection lost")
aiosmtplib.errors.SMTPServerDisconnected: Connection lost

and this is my code:

@router.post("/users/send_validation_email/{email}", tags=["users"],
            responses={
                400: {"description": "The user's email has been already verified"},
                404: {"description": "User not found"}
            }
)
async def send_validation_email(email: str, lang: str, background_tasks: BackgroundTasks):

    user = users_crud.get_user_by_email(email=email)

    if user is None:
        raise HTTPException(status_code=404, detail="User not found")
    elif user is not None and user["email_verified"] is True:
        raise HTTPException(status_code=400, detail="The user's email has been already verified")

    message = email_utils.get_validation_mail(user_id=str(user["_id"]), email_address=user["email"], user_name=user['first_name'], lang=lang)

    if message is not None:
        fm = FastMail(conf)
        #background_tasks.add_task(fm.send_message, message)
        await fm.send_message(message)

    return JSONResponse(status_code=200, content={"message": "email has been sent"})

I tried using both BackgroundTasks and await but the result is the same: on my local machine it sends the email and on the DigitalOcean virtual server doesn't. Do you have any suggestions?

Which protocol uses fastapi-mail?

Hello to all members! I have a question, it's a bit not clear for me. Which protocol uses fastapi-mail for sending messages to SMTP server? Is it SMTP or HTTPS or smt else?

await fm.send_message(message)

Features utils

I would like to have some additional features of this module. For example, check MX records, whether the address is temporary. I would like to add a blocking email address or domain

test_redis_config failing

@Turall
The unit test for test_redis_checker in test_redis_config fails with ConnectionRefusedError: [Errno 111] Connect call failed ('127.0.0.1', 6379)
I speculate it is because I do not have a Redis server turned on and I believe it might be a little better if you used mocking in conjunction with those partcular tests: I would rather not have to turn on a Redis server everytime I want to run a test for fastapi-mail.

Allow creating custom headers for attachments

Use case - attaching html images with Content-ID header to reference them in HTML content of email based on RFC2392

How to do it:

  • Modify MessageSchema to allow setting custom headers, like this
message = MessageSchema(
        subject=subject,
        recipients=recipients,
        html=html,
        subtype="html",
        attachments=[{"file": "/path/to/file", "headers":{"Content-ID": "<image1>"}, "mime_type" : "image", "mime_subtype": "png"}]
    )

file parameter can be as now, UploadFile and path

As it's hard to automagically import mime class as they dont' have the same API, it's possible to do it through MIMEBase

So it's possible to add custom headers and override mime_type used in MIMEBase with type and subtype attributes

and in MailMsg, in attach_file method, unpack the structure and add headers.

I can code it if this is fine @sabuhish

Jinja2 templates not getting populated with body

I'm trying to send an HTML rendered email with Jinja2 templates, but no context is being send.

Here's an example of the message I'm sending...

message = MessageSchema(
    subject="Grove Password Reset",
    recipients=[form.email],
    body={"email": email, "other": "some random string"},
    subtype="html",
)

fast_mail = FastMail(settings.EMAIL_CONFIG)

background_tasks.add_task(fast_mail.send_message, message, template_name="template.html")

The email is sent correctly, and the template shows up as a rendered HTML email, but none of the information from the body parameter gets rendered.

fastapi 0.70.0

fastapi 0.70.0

Because fastapi-mail (1.0.1) depends on fastapi (>=0.68.1,<0.69.0)
and no versions of fastapi-mail match >1.0.1,<2.0.0, fastapi-mail (>=1.0.1,<2.0.0) requires fastapi (>=0.68.1,<0.69.0).
So, because hashjump co api depends on both fastapi (^0.70.0) and fastapi-mail (^1.0.1), version solving failed.

create a tutorial for basic use

Hey I don't know if it is ok to ask but, I tried to copy the examples and changed them to my own credentials, yet it still doesn't work
can you please put on a beginners guide or something so it would be easier to access?
thanks in advance!

Valid path raises TemplateFolderDoesNotExist in ConnectionConfig

I was using fastapi-mail 0.3.7 and it worked. When I upgraded it to 0.4.1, it started showing a TemplateFolderDoesNotExist error for the same path that was valid for the previous version.

The file is located at /tmp/republicaos/app/mailer.py:

from pathlib import Path

from fastapi_mail import ConnectionConfig, FastMail

from . import config


templates_path = Path(__file__).parent / 'templates'
conf = ConnectionConfig(
    MAIL_USERNAME=config.MAIL_USERNAME,
    MAIL_PASSWORD=config.MAIL_PASSWORD,
    MAIL_FROM=config.MAIL_FROM,
    MAIL_PORT=config.DB_PORT,
    MAIL_SERVER=config.MAIL_SERVER,
    MAIL_FROM_NAME=config.MAIL_FROM_NAME,
    MAIL_TLS=True,
    MAIL_SSL=False,
    USE_CREDENTIALS=True,
    MAIL_DEBUG=config.DEBUG,
    SUPPRESS_SEND=config.DEBUG or config.TESTING,
    TEMPLATE_FOLDER=templates_path,
)

mailer = FastMail(conf)

And the error I get is:

  File "/tmp/republicaos/app/mailer.py", line 10, in <module>
    conf = ConnectionConfig(
  File "pydantic/env_settings.py", line 36, in pydantic.env_settings.BaseSettings.__init__
  File "pydantic/main.py", line 404, in pydantic.main.BaseModel.__init__
  File "pydantic/main.py", line 1040, in pydantic.main.validate_model
  File "pydantic/fields.py", line 737, in pydantic.fields.ModelField.validate
  File "pydantic/fields.py", line 913, in pydantic.fields.ModelField._apply_validators
  File "pydantic/class_validators.py", line 277, in pydantic.class_validators._generic_validator_cls.lambda3
  File "/tmp/republicaos/.venv/lib/python3.9/site-packages/fastapi_mail/config.py", line 33, in template_folder_validator
    raise TemplateFolderDoesNotExist(
fastapi_mail.errors.TemplateFolderDoesNotExist: PosixPath('/tmp/republicaos/app/templates') is not a valid path to an email template folder

Important: /tmp/republicaos/app/templates exists and contains a few files.

It seems related to #63 as implemented by @kucera-lukas

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.